Skip to content

Commit 109f2dd

Browse files
committed
Add new error comparision to hide desugaring
First some background: To the compiler, the following two signatures in the trait vs the impl are the same. ```rust trait Foo { fn foo(&self, &impl Debug); } impl Foo for () { fn foo<U: Debug>(&self, x: &U) { ... } } ``` We do not want to allow this, and so we add a new error and check. The check just tests that all paramters 'syntheticness' match up. As during collection, the impl Trait parameters are transformed into anonymous synthetic generics. Furthermore, causes a check for unused type parameters to be skipped in check_bounds_are_used if there is already a TyError. Thus, an unused input will not trigger `type parameter unused` errors. Update the one test that checked for this error in the case of a TyError.
1 parent f225fe4 commit 109f2dd

File tree

4 files changed

+68
-13
lines changed

4 files changed

+68
-13
lines changed

src/librustc_typeck/check/compare_method.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
6767
return;
6868
}
6969

70+
if let Err(ErrorReported) = compare_synthetic_generics(tcx,
71+
impl_m,
72+
impl_m_span,
73+
trait_m,
74+
trait_item_span) {
75+
return;
76+
}
77+
7078
if let Err(ErrorReported) = compare_predicate_entailment(tcx,
7179
impl_m,
7280
impl_m_span,
@@ -708,6 +716,45 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
708716
Ok(())
709717
}
710718

719+
fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
720+
impl_m: &ty::AssociatedItem,
721+
_impl_m_span: Span, // FIXME necessary?
722+
trait_m: &ty::AssociatedItem,
723+
_trait_item_span: Option<Span>) // FIXME necessary?
724+
-> Result<(), ErrorReported> {
725+
// FIXME(chrisvittal) Clean up this function, list of FIXME items:
726+
// 1. Better messages for the span lables
727+
// 2. Explanation as to what is going on
728+
// 3. Correct the function signature for what we actually use
729+
// If we get here, we already have the same number of generics, so the zip will
730+
// be okay.
731+
let mut error_found = false;
732+
let impl_m_generics = tcx.generics_of(impl_m.def_id);
733+
let trait_m_generics = tcx.generics_of(trait_m.def_id);
734+
for (impl_ty, trait_ty) in impl_m_generics.types.iter().zip(trait_m_generics.types.iter()) {
735+
if impl_ty.synthetic != trait_ty.synthetic {
736+
let impl_node_id = tcx.hir.as_local_node_id(impl_ty.def_id).unwrap();
737+
let impl_span = tcx.hir.span(impl_node_id);
738+
let trait_node_id = tcx.hir.as_local_node_id(trait_ty.def_id).unwrap();
739+
let trait_span = tcx.hir.span(trait_node_id);
740+
let mut err = struct_span_err!(tcx.sess,
741+
impl_span,
742+
E0642,
743+
"method `{}` has incompatible signature for trait",
744+
trait_m.name);
745+
err.span_label(trait_span, "annotation in trait");
746+
err.span_label(impl_span, "annotation in impl");
747+
err.emit();
748+
error_found = true;
749+
}
750+
}
751+
if error_found {
752+
Err(ErrorReported)
753+
} else {
754+
Ok(())
755+
}
756+
}
757+
711758
pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
712759
impl_c: &ty::AssociatedItem,
713760
impl_c_span: Span,

src/librustc_typeck/check/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5035,6 +5035,10 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
50355035
if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
50365036
debug!("Found use of ty param num {}", idx);
50375037
tps_used[idx as usize - generics.lifetimes.len()] = true;
5038+
} else if let ty::TyError = leaf_ty.sty {
5039+
// If there already another error, do not emit an error for not using a type Parameter
5040+
assert!(tcx.sess.err_count() > 0);
5041+
return;
50385042
}
50395043
}
50405044

src/librustc_typeck/diagnostics.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4625,6 +4625,22 @@ It is recommended that you look for a `new` function or equivalent in the
46254625
crate's documentation.
46264626
"##,
46274627

4628+
E0642: r##"
4629+
This error indicates that there is a mismatch between generic parameters and
4630+
impl Trait parameters in a trait Declaration versus it's impl.
4631+
4632+
```compile_fail,E0642
4633+
#![feature(conservative_impl_trait)]
4634+
trait Foo
4635+
fn foo(&self, &impl Iterator)
4636+
}
4637+
impl Foo for () {
4638+
fn foo<U: Iterator>(&self, _: &U) { } // error method `foo` has incompatible
4639+
// signature for trait
4640+
}
4641+
```
4642+
"##,
4643+
46284644
}
46294645

46304646
register_diagnostics! {

src/test/ui/resolve/use_suggestion_placement.stderr

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,5 @@ help: possible candidates are found in other modules, you can import them into s
3333
11 | use std::collections::hash_map::HashMap;
3434
|
3535

36-
error[E0091]: type parameter `K` is unused
37-
--> $DIR/use_suggestion_placement.rs:35:15
38-
|
39-
35 | type Dict<K, V> = HashMap<K, V>;
40-
| ^ unused type parameter
41-
42-
error[E0091]: type parameter `V` is unused
43-
--> $DIR/use_suggestion_placement.rs:35:18
44-
|
45-
35 | type Dict<K, V> = HashMap<K, V>;
46-
| ^ unused type parameter
47-
48-
error: aborting due to 5 previous errors
36+
error: aborting due to 3 previous errors
4937

0 commit comments

Comments
 (0)