Skip to content
Closed
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
39466bc
implement Error for &(impl Error)
KodrAus Aug 5, 2020
573ec31
update stabilization to 1.49.0
KodrAus Oct 31, 2020
bbf5001
bump stabilization to 1.51.0
KodrAus Dec 21, 2020
7378676
Fix sysroot option not being honored across rustc
rcvalle Jan 20, 2021
3e9f27d
Remove unnecessary closure
bugadani Jan 22, 2021
58a90de
No peeking
bugadani Jan 22, 2021
9988821
Move missing_item check inside condition
bugadani Jan 22, 2021
d63b278
Only scan through assoc items once in check_impl_items_against_trait
bugadani Jan 22, 2021
ee639de
Only guess span if absolutely necessary
bugadani Jan 22, 2021
aa4f583
Only query associated_items once
bugadani Jan 22, 2021
f29b329
Fix formatting
bugadani Jan 22, 2021
99a1dea
Do not mark unit variants as used when in path pattern
tmiasko Jan 23, 2021
794880c
Don't provide backend_optimization_level query for extern crates
bjorn3 Jan 23, 2021
d118021
Permit mutable references in all const contexts
oli-obk Jan 3, 2021
b217fab
Rename tests to what their code actually does
oli-obk Jan 16, 2021
3cd0b46
Fix a comment that only made sense in the context of a dataflow based…
oli-obk Jan 16, 2021
00e62fa
Adjust wording of a diagnostic
oli-obk Jan 16, 2021
14f39aa
Do not allow arbitrary mutable references in `static mut`, just keep …
oli-obk Jan 16, 2021
cd09871
Cover more cases in the test suite
oli-obk Jan 23, 2021
819b008
Put dynamic check tests into their own file
oli-obk Jan 23, 2021
1129e86
Cleanup `render_stability_since_raw` to remove code duplication
LeSeulArtichaut Jan 23, 2021
9b1d27d
Add option to control doctest run directory
Swatinem Jan 22, 2021
20a460e
Fix rendering of stabilization version for trait implementors
LeSeulArtichaut Jan 23, 2021
14aa12f
Replace version_check dependency with own version parsing code
est31 Jan 22, 2021
f8416fa
Clean up dominators_given_rpo
bugadani Jan 24, 2021
08c01f8
Fix flaky test
jyn514 Jan 19, 2021
67815d1
Rollup merge of #75180 - KodrAus:feat/error-by-ref, r=m-ou-se
jonas-schievink Jan 24, 2021
9e0a84e
Rollup merge of #78578 - oli-obk:const_mut_refs, r=RalfJung
jonas-schievink Jan 24, 2021
879f3b7
Rollup merge of #80933 - rcvalle:fix-sysroot-option, r=nagisa
jonas-schievink Jan 24, 2021
5836c45
Rollup merge of #81197 - jyn514:flaky-test, r=Mark-Simulacrum
jonas-schievink Jan 24, 2021
7d91b36
Rollup merge of #81259 - est31:cfg_version, r=petrochenkov
jonas-schievink Jan 24, 2021
5f300cd
Rollup merge of #81264 - Swatinem:doctest-run-directory, r=jyn514
jonas-schievink Jan 24, 2021
1a3b6b9
Rollup merge of #81279 - bugadani:iter, r=davidtwco
jonas-schievink Jan 24, 2021
372827a
Rollup merge of #81297 - bjorn3:no_extern_backend_optimization_level_…
jonas-schievink Jan 24, 2021
18c8413
Rollup merge of #81302 - LeSeulArtichaut:80777-trait-render, r=jyn514
jonas-schievink Jan 24, 2021
d963e71
Rollup merge of #81310 - tmiasko:in-pattern, r=petrochenkov
jonas-schievink Jan 24, 2021
58a330d
Rollup merge of #81338 - bugadani:dominator-cleanup, r=davidtwco
jonas-schievink Jan 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Only scan through assoc items once in check_impl_items_against_trait
  • Loading branch information
bugadani committed Jan 22, 2021
commit d63b278c2ff01b73653397a5e2c469689ef0adf4
215 changes: 117 additions & 98 deletions compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,15 +846,13 @@ pub(super) fn check_specialization_validity<'tcx>(
Ok(ancestors) => ancestors,
Err(_) => return,
};
let mut ancestor_impls = ancestors
.skip(1)
.filter_map(|parent| {
if parent.is_from_trait() {
None
} else {
Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id)))
}
});
let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| {
if parent.is_from_trait() {
None
} else {
Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id)))
}
});

let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| {
match parent_item {
Expand Down Expand Up @@ -931,105 +929,72 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
// Check existing impl methods to see if they are both present in trait
// and compatible with trait signature
for impl_item in impl_items {
let namespace = impl_item.kind.namespace();
let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id));
let ty_trait_item = tcx
.associated_items(impl_trait_ref.def_id)
.find_by_name_and_namespace(tcx, ty_impl_item.ident, namespace, impl_trait_ref.def_id)
.or_else(|| {
// Not compatible, but needed for the error message
tcx.associated_items(impl_trait_ref.def_id)
.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id)
.next()
});

// Check that impl definition matches trait definition
if let Some(ty_trait_item) = ty_trait_item {
let associated_items = tcx.associated_items(impl_trait_ref.def_id);

let mut items = associated_items.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id);

let (compatible_kind, ty_trait_item) = if let Some(ty_trait_item) = items.next() {

let is_compatible = |ty: &&ty::AssocItem| {
match (ty.kind, &impl_item.kind) {
(ty::AssocKind::Const, hir::ImplItemKind::Const(..)) => true,
(ty::AssocKind::Fn, hir::ImplItemKind::Fn(..)) => true,
(ty::AssocKind::Type, hir::ImplItemKind::TyAlias(..)) => true,
_ => false
}
};

// If we don't have a compatible item, we'll use the first one whose name matches
// to report an error.
let mut compatible_kind = is_compatible(&ty_trait_item);
let mut trait_item = ty_trait_item;

if !compatible_kind {
if let Some(ty_trait_item) = items.find(is_compatible) {
compatible_kind = true;
trait_item = ty_trait_item;
}
}

(compatible_kind, trait_item)
} else {
continue;
};

if compatible_kind {
match impl_item.kind {
hir::ImplItemKind::Const(..) => {
// Find associated const definition.
if ty_trait_item.kind == ty::AssocKind::Const {
compare_const_impl(
tcx,
&ty_impl_item,
impl_item.span,
&ty_trait_item,
impl_trait_ref,
);
} else {
let mut err = struct_span_err!(
tcx.sess,
impl_item.span,
E0323,
"item `{}` is an associated const, \
which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref.print_only_trait_path()
);
err.span_label(impl_item.span, "does not match trait");
// We can only get the spans from local trait definition
// Same for E0324 and E0325
if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
err.span_label(trait_span, "item in trait");
}
err.emit()
}
compare_const_impl(
tcx,
&ty_impl_item,
impl_item.span,
&ty_trait_item,
impl_trait_ref,
);
}
hir::ImplItemKind::Fn(..) => {
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
if ty_trait_item.kind == ty::AssocKind::Fn {
compare_impl_method(
tcx,
&ty_impl_item,
impl_item.span,
&ty_trait_item,
impl_trait_ref,
opt_trait_span,
);
} else {
let mut err = struct_span_err!(
tcx.sess,
impl_item.span,
E0324,
"item `{}` is an associated method, \
which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref.print_only_trait_path()
);
err.span_label(impl_item.span, "does not match trait");
if let Some(trait_span) = opt_trait_span {
err.span_label(trait_span, "item in trait");
}
err.emit()
}
compare_impl_method(
tcx,
&ty_impl_item,
impl_item.span,
&ty_trait_item,
impl_trait_ref,
opt_trait_span,
);
}
hir::ImplItemKind::TyAlias(_) => {
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
if ty_trait_item.kind == ty::AssocKind::Type {
compare_ty_impl(
tcx,
&ty_impl_item,
impl_item.span,
&ty_trait_item,
impl_trait_ref,
opt_trait_span,
);
} else {
let mut err = struct_span_err!(
tcx.sess,
impl_item.span,
E0325,
"item `{}` is an associated type, \
which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref.print_only_trait_path()
);
err.span_label(impl_item.span, "does not match trait");
if let Some(trait_span) = opt_trait_span {
err.span_label(trait_span, "item in trait");
}
err.emit()
}
compare_ty_impl(
tcx,
&ty_impl_item,
impl_item.span,
&ty_trait_item,
impl_trait_ref,
opt_trait_span,
);
}
}

Expand All @@ -1040,6 +1005,8 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
impl_id.to_def_id(),
impl_item,
);
} else {
report_mismatch_error(tcx, ty_trait_item.def_id, impl_trait_ref, impl_item, &ty_impl_item);
}
}

Expand All @@ -1065,6 +1032,58 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
}
}

#[inline(never)]
#[cold]
fn report_mismatch_error<'tcx>(
tcx: TyCtxt<'tcx>,
trait_item_def_id: DefId,
impl_trait_ref: ty::TraitRef<'tcx>,
impl_item: &hir::ImplItem<'_>,
ty_impl_item: &ty::AssocItem,
) {
let mut err = match impl_item.kind {
hir::ImplItemKind::Const(..) => {
// Find associated const definition.
struct_span_err!(
tcx.sess,
impl_item.span,
E0323,
"item `{}` is an associated const, which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref.print_only_trait_path()
)
}

hir::ImplItemKind::Fn(..) => {
struct_span_err!(
tcx.sess,
impl_item.span,
E0324,
"item `{}` is an associated method, which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref.print_only_trait_path()
)
}

hir::ImplItemKind::TyAlias(_) => {
struct_span_err!(
tcx.sess,
impl_item.span,
E0325,
"item `{}` is an associated type, which doesn't match its trait `{}`",
ty_impl_item.ident,
impl_trait_ref.print_only_trait_path()
)
}
};

err.span_label(impl_item.span, "does not match trait");
if let Some(trait_span) = tcx.hir().span_if_local(trait_item_def_id) {
err.span_label(trait_span, "item in trait");
}
err.emit();
}

/// Checks whether a type can be represented in memory. In particular, it
/// identifies types that contain themselves without indirection through a
/// pointer, which would mean their size is unbounded.
Expand Down