Skip to content

Suggest correct syntax when writing type arg instead of assoc type #55808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 23, 2018
Merged
Changes from all commits
Commits
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
181 changes: 121 additions & 60 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -182,7 +182,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
item_segment: &hir::PathSegment)
-> &'tcx Substs<'tcx>
{
let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| {
let (substs, assoc_bindings, _) = item_segment.with_generic_args(|generic_args| {
self.create_substs_for_ast_path(
span,
def_id,
@@ -256,7 +256,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
},
def.parent.is_none() && def.has_self, // `has_self`
seg.infer_types || suppress_mismatch, // `infer_types`
)
).0
}

/// Check that the correct number of generic arguments have been provided.
@@ -269,7 +269,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
position: GenericArgPosition,
has_self: bool,
infer_types: bool,
) -> bool {
) -> (bool, Option<Vec<Span>>) {
// At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
// that lifetimes will proceed types. So it suffices to check the number of each generic
// arguments in order to validate them with respect to the generic parameters.
@@ -303,13 +303,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
let mut err = tcx.sess.struct_span_err(span, msg);
err.span_note(span_late, note);
err.emit();
return true;
return (true, None);
} else {
let mut multispan = MultiSpan::from_span(span);
multispan.push_span_label(span_late, note.to_string());
tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
args.args[0].id(), multispan, msg);
return false;
return (false, None);
}
}
}
@@ -323,7 +323,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
// For kinds without defaults (i.e. lifetimes), `required == permitted`.
// For other kinds (i.e. types), `permitted` may be greater than `required`.
if required <= provided && provided <= permitted {
return false;
return (false, None);
}

// Unfortunately lifetime and type parameter mismatches are typically styled
@@ -338,33 +338,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
(required, "")
};

let mut span = span;
let label = if required == permitted && provided > permitted {
let diff = provided - permitted;
if diff == 1 {
// In the case when the user has provided too many arguments,
// we want to point to the first unexpected argument.
let first_superfluous_arg: &GenericArg = &args.args[offset + permitted];
span = first_superfluous_arg.span();
}
format!(
"{}unexpected {} argument{}",
if diff != 1 { format!("{} ", diff) } else { String::new() },
kind,
if diff != 1 { "s" } else { "" },
)
let mut potential_assoc_types: Option<Vec<Span>> = None;
let (spans, label) = if required == permitted && provided > permitted {
// In the case when the user has provided too many arguments,
// we want to point to the unexpected arguments.
let spans: Vec<Span> = args.args[offset+permitted .. offset+provided]
.iter()
.map(|arg| arg.span())
.collect();
potential_assoc_types = Some(spans.clone());
(spans, format!( "unexpected {} argument", kind))
} else {
format!(
(vec![span], format!(
"expected {}{} {} argument{}",
quantifier,
bound,
kind,
if bound != 1 { "s" } else { "" },
)
))
};

tcx.sess.struct_span_err_with_code(
span,
let mut err = tcx.sess.struct_span_err_with_code(
spans.clone(),
&format!(
"wrong number of {} arguments: expected {}{}, found {}",
kind,
@@ -373,9 +368,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
provided,
),
DiagnosticId::Error("E0107".into())
).span_label(span, label).emit();
);
for span in spans {
err.span_label(span, label.as_str());
}
err.emit();

provided > required // `suppress_error`
(provided > required, // `suppress_error`
potential_assoc_types)
};

if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
@@ -397,7 +397,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
arg_counts.lifetimes,
)
} else {
false
(false, None)
}
}

@@ -555,7 +555,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
generic_args: &hir::GenericArgs,
infer_types: bool,
self_ty: Option<Ty<'tcx>>)
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>)
{
// If the type is parameterized by this region, then replace this
// region with the current anon region binding (in other words,
@@ -571,7 +571,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
assert_eq!(generic_params.has_self, self_ty.is_some());

let has_self = generic_params.has_self;
Self::check_generic_arg_count(
let (_, potential_assoc_types) = Self::check_generic_arg_count(
self.tcx(),
span,
&generic_params,
@@ -676,7 +676,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
debug!("create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
generic_params, self_ty, substs);

(substs, assoc_bindings)
(substs, assoc_bindings, potential_assoc_types)
}

/// Instantiates the path for the given trait reference, assuming that it's
@@ -718,19 +718,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
self_ty: Ty<'tcx>,
poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
speculative: bool)
-> ty::PolyTraitRef<'tcx>
-> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
{
let trait_def_id = self.trait_def_id(trait_ref);

debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);

self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);

let (substs, assoc_bindings) =
self.create_substs_for_ast_trait_ref(trait_ref.path.span,
trait_def_id,
self_ty,
trait_ref.path.segments.last().unwrap());
let (substs, assoc_bindings, potential_assoc_types) = self.create_substs_for_ast_trait_ref(
trait_ref.path.span,
trait_def_id,
self_ty,
trait_ref.path.segments.last().unwrap(),
);
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));

let mut dup_bindings = FxHashMap::default();
@@ -745,14 +746,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {

debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}",
trait_ref, poly_projections, poly_trait_ref);
poly_trait_ref
(poly_trait_ref, potential_assoc_types)
}

pub fn instantiate_poly_trait_ref(&self,
poly_trait_ref: &hir::PolyTraitRef,
self_ty: Ty<'tcx>,
poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>)
-> ty::PolyTraitRef<'tcx>
-> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
{
self.instantiate_poly_trait_ref_inner(&poly_trait_ref.trait_ref, self_ty,
poly_projections, false)
@@ -765,7 +766,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
trait_segment: &hir::PathSegment)
-> ty::TraitRef<'tcx>
{
let (substs, assoc_bindings) =
let (substs, assoc_bindings, _) =
self.create_substs_for_ast_trait_ref(span,
trait_def_id,
self_ty,
@@ -774,13 +775,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
ty::TraitRef::new(trait_def_id, substs)
}

fn create_substs_for_ast_trait_ref(&self,
span: Span,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment)
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
{
fn create_substs_for_ast_trait_ref(
&self,
span: Span,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment,
) -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>) {
debug!("create_substs_for_ast_trait_ref(trait_segment={:?})",
trait_segment);

@@ -970,9 +971,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {

let mut projection_bounds = Vec::new();
let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
let principal = self.instantiate_poly_trait_ref(&trait_bounds[0],
dummy_self,
&mut projection_bounds);
let (principal, potential_assoc_types) = self.instantiate_poly_trait_ref(
&trait_bounds[0],
dummy_self,
&mut projection_bounds,
);
debug!("principal: {:?}", principal);

for trait_bound in trait_bounds[1..].iter() {
@@ -1027,16 +1030,74 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
associated_types.remove(&projection_bound.projection_def_id());
}

for item_def_id in associated_types {
let assoc_item = tcx.associated_item(item_def_id);
let trait_def_id = assoc_item.container.id();
struct_span_err!(tcx.sess, span, E0191, "the value of the associated type `{}` \
(from the trait `{}`) must be specified",
assoc_item.ident,
tcx.item_path_str(trait_def_id))
.span_label(span, format!("missing associated type `{}` value",
assoc_item.ident))
.emit();
if !associated_types.is_empty() {
let names = associated_types.iter().map(|item_def_id| {
let assoc_item = tcx.associated_item(*item_def_id);
let trait_def_id = assoc_item.container.id();
format!(
"`{}` (from the trait `{}`)",
assoc_item.ident,
tcx.item_path_str(trait_def_id),
)
}).collect::<Vec<_>>().join(", ");
let mut err = struct_span_err!(
tcx.sess,
span,
E0191,
"the value of the associated type{} {} must be specified",
if associated_types.len() == 1 { "" } else { "s" },
names,
);
let mut suggest = false;
let mut potential_assoc_types_spans = vec![];
if let Some(potential_assoc_types) = potential_assoc_types {
if potential_assoc_types.len() == associated_types.len() {
// Only suggest when the amount of missing associated types is equals to the
// extra type arguments present, as that gives us a relatively high confidence
// that the user forgot to give the associtated type's name. The canonical
// example would be trying to use `Iterator<isize>` instead of
// `Iterator<Item=isize>`.
suggest = true;
potential_assoc_types_spans = potential_assoc_types;
}
}
let mut suggestions = vec![];
for (i, item_def_id) in associated_types.iter().enumerate() {
let assoc_item = tcx.associated_item(*item_def_id);
err.span_label(
span,
format!("associated type `{}` must be specified", assoc_item.ident),
);
if item_def_id.is_local() {
err.span_label(
tcx.def_span(*item_def_id),
format!("`{}` defined here", assoc_item.ident),
);
}
if suggest {
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(
potential_assoc_types_spans[i],
) {
suggestions.push((
potential_assoc_types_spans[i],
format!("{} = {}", assoc_item.ident, snippet),
));
}
}
}
if !suggestions.is_empty() {
let msg = if suggestions.len() == 1 {
"if you meant to specify the associated type, write"
} else {
"if you meant to specify the associated types, write"
};
err.multipart_suggestion_with_applicability(
msg,
suggestions,
Applicability::MaybeIncorrect,
);
}
err.emit();
}

// Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
11 changes: 8 additions & 3 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
@@ -1892,7 +1892,7 @@ fn explicit_predicates_of<'a, 'tcx>(
&hir::GenericBound::Trait(ref poly_trait_ref, _) => {
let mut projections = Vec::new();

let trait_ref = AstConv::instantiate_poly_trait_ref(
let (trait_ref, _) = AstConv::instantiate_poly_trait_ref(
&icx,
poly_trait_ref,
ty,
@@ -2016,7 +2016,12 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
let mut projection_bounds = Vec::new();

let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
(astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds), bound.span)
let (poly_trait_ref, _) = astconv.instantiate_poly_trait_ref(
bound,
param_ty,
&mut projection_bounds,
);
(poly_trait_ref, bound.span)
}).collect();

let region_bounds = region_bounds
@@ -2057,7 +2062,7 @@ fn predicates_from_bound<'tcx>(
match *bound {
hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
let mut projections = Vec::new();
let pred = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections);
let (pred, _) = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut projections);
iter::once((pred.to_predicate(), tr.span)).chain(
projections
.into_iter()
2 changes: 1 addition & 1 deletion src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
@@ -389,7 +389,7 @@ pub fn hir_trait_to_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir_trait:
let env_def_id = tcx.hir.local_def_id(env_node_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id);
let mut projections = Vec::new();
let principal = astconv::AstConv::instantiate_poly_trait_ref_inner(
let (principal, _) = astconv::AstConv::instantiate_poly_trait_ref_inner(
&item_cx, hir_trait, tcx.types.err, &mut projections, true
);

4 changes: 1 addition & 3 deletions src/test/compile-fail/issue-23595-1.rs
Original file line number Diff line number Diff line change
@@ -16,9 +16,7 @@ trait Hierarchy {
type Value;
type ChildKey;
type Children = Index<Self::ChildKey, Output=Hierarchy>;
//~^ ERROR: the value of the associated type `ChildKey`
//~^^ ERROR: the value of the associated type `Children`
//~^^^ ERROR: the value of the associated type `Value`
//~^ ERROR: the value of the associated types `Value` (from the trait `Hierarchy`), `ChildKey`

fn data(&self) -> Option<(Self::Value, Self::Children)>;
}
Original file line number Diff line number Diff line change
@@ -25,8 +25,11 @@ LL | fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
error[E0191]: the value of the associated type `Color` (from the trait `Vehicle`) must be specified
--> $DIR/associated-type-projection-from-multiple-supertraits.rs:33:26
|
LL | type Color;
| ----------- `Color` defined here
...
LL | fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
| ^^^^^^^^^^^^^^^^^^^ missing associated type `Color` value
| ^^^^^^^^^^^^^^^^^^^ associated type `Color` must be specified

error[E0221]: ambiguous associated type `Color` in bounds of `C`
--> $DIR/associated-type-projection-from-multiple-supertraits.rs:38:29
Original file line number Diff line number Diff line change
@@ -37,6 +37,5 @@ pub fn main() {
//~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified

let d = &42isize as &Foo;
//~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
//~| ERROR the value of the associated type `B` (from the trait `Foo`) must be specified
//~^ ERROR the value of the associated types `A` (from the trait `Foo`), `B` (from the trait
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
error[E0191]: the value of the associated type `B` (from the trait `Foo`) must be specified
--> $DIR/associated-types-incomplete-object.rs:33:26
|
LL | type B;
| ------- `B` defined here
...
LL | let b = &42isize as &Foo<A=usize>;
| ^^^^^^^^^^^^ missing associated type `B` value
| ^^^^^^^^^^^^ associated type `B` must be specified

error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified
--> $DIR/associated-types-incomplete-object.rs:36:26
|
LL | type A;
| ------- `A` defined here
...
LL | let c = &42isize as &Foo<B=char>;
| ^^^^^^^^^^^ missing associated type `A` value
| ^^^^^^^^^^^ associated type `A` must be specified

error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified
--> $DIR/associated-types-incomplete-object.rs:39:26
|
LL | let d = &42isize as &Foo;
| ^^^ missing associated type `A` value

error[E0191]: the value of the associated type `B` (from the trait `Foo`) must be specified
error[E0191]: the value of the associated types `A` (from the trait `Foo`), `B` (from the trait `Foo`) must be specified
--> $DIR/associated-types-incomplete-object.rs:39:26
|
LL | type A;
| ------- `A` defined here
LL | type B;
| ------- `B` defined here
...
LL | let d = &42isize as &Foo;
| ^^^ missing associated type `B` value
| ^^^
| |
| associated type `A` must be specified
| associated type `B` must be specified

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0191`.
3 changes: 2 additions & 1 deletion src/test/ui/error-codes/E0107.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,8 @@ struct Baz<'a, 'b, 'c> {
//~| unexpected lifetime argument
foo2: Foo<'a, 'b, 'c>,
//~^ ERROR E0107
//~| 2 unexpected lifetime arguments
//~| unexpected lifetime argument
//~| unexpected lifetime argument
}

fn main() {}
6 changes: 4 additions & 2 deletions src/test/ui/error-codes/E0107.stderr
Original file line number Diff line number Diff line change
@@ -11,10 +11,12 @@ LL | bar: Bar<'a>,
| ^^ unexpected lifetime argument

error[E0107]: wrong number of lifetime arguments: expected 1, found 3
--> $DIR/E0107.rs:27:11
--> $DIR/E0107.rs:27:19
|
LL | foo2: Foo<'a, 'b, 'c>,
| ^^^^^^^^^^^^^^^ 2 unexpected lifetime arguments
| ^^ ^^ unexpected lifetime argument
| |
| unexpected lifetime argument

error: aborting due to 3 previous errors

5 changes: 4 additions & 1 deletion src/test/ui/error-codes/E0191.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified
--> $DIR/E0191.rs:15:12
|
LL | type Bar;
| --------- `Bar` defined here
...
LL | type Foo = Trait; //~ ERROR E0191
| ^^^^^ missing associated type `Bar` value
| ^^^^^ associated type `Bar` must be specified

error: aborting due to previous error

5 changes: 4 additions & 1 deletion src/test/ui/error-codes/E0220.stderr
Original file line number Diff line number Diff line change
@@ -7,8 +7,11 @@ LL | type Foo = Trait<F=i32>; //~ ERROR E0220
error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified
--> $DIR/E0220.rs:15:12
|
LL | type Bar;
| --------- `Bar` defined here
...
LL | type Foo = Trait<F=i32>; //~ ERROR E0220
| ^^^^^^^^^^^^ missing associated type `Bar` value
| ^^^^^^^^^^^^ associated type `Bar` must be specified

error: aborting due to 2 previous errors

5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-19482.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified
--> $DIR/issue-19482.rs:20:12
|
LL | type A;
| ------- `A` defined here
...
LL | fn bar(x: &Foo) {}
| ^^^ missing associated type `A` value
| ^^^ associated type `A` must be specified

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-21950.stderr
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op
--> $DIR/issue-21950.rs:17:14
|
LL | &Add;
| ^^^ missing associated type `Output` value
| ^^^ associated type `Output` must be specified

error: aborting due to 2 previous errors

5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-22434.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified
--> $DIR/issue-22434.rs:15:19
|
LL | type A;
| ------- `A` defined here
...
LL | type I<'a> = &'a (Foo + 'a);
| ^^^^^^^^ missing associated type `A` value
| ^^^^^^^^ associated type `A` must be specified

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-22560.stderr
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ LL | type Test = Add +
LL | | //~^ ERROR E0393
LL | | //~| ERROR E0191
LL | | Sub;
| |_______________^ missing associated type `Output` value
| |_______________^ associated type `Output` must be specified

error: aborting due to 4 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-23024.stderr
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op
--> $DIR/issue-23024.rs:19:35
|
LL | println!("{:?}",(vfnfer[0] as Fn)(3));
| ^^ missing associated type `Output` value
| ^^ associated type `Output` must be specified

error: aborting due to 3 previous errors

4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-28344.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op
--> $DIR/issue-28344.rs:14:17
|
LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
| ^^^^^^^^^^^^^ missing associated type `Output` value
| ^^^^^^^^^^^^^ associated type `Output` must be specified

error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
--> $DIR/issue-28344.rs:14:17
@@ -16,7 +16,7 @@ error[E0191]: the value of the associated type `Output` (from the trait `std::op
--> $DIR/issue-28344.rs:18:13
|
LL | let g = BitXor::bitor;
| ^^^^^^^^^^^^^ missing associated type `Output` value
| ^^^^^^^^^^^^^ associated type `Output` must be specified

error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope
--> $DIR/issue-28344.rs:18:13
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub trait T<X, Y> {
type A;
type B;
type C;
}
pub struct Foo { i: Box<T<usize, usize, usize, usize, B=usize>> }

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
error[E0107]: wrong number of type arguments: expected 2, found 4
--> $DIR/use-type-argument-instead-of-assoc-type.rs:6:42
|
LL | pub struct Foo { i: Box<T<usize, usize, usize, usize, B=usize>> }
| ^^^^^ ^^^^^ unexpected type argument
| |
| unexpected type argument

error[E0191]: the value of the associated types `A` (from the trait `T`), `C` (from the trait `T`) must be specified
--> $DIR/use-type-argument-instead-of-assoc-type.rs:6:26
|
LL | type A;
| ------- `A` defined here
LL | type B;
LL | type C;
| ------- `C` defined here
LL | }
LL | pub struct Foo { i: Box<T<usize, usize, usize, usize, B=usize>> }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| associated type `A` must be specified
| associated type `C` must be specified
help: if you meant to specify the associated types, write
|
LL | pub struct Foo { i: Box<T<usize, usize, A = usize, C = usize, B=usize>> }
| ^^^^^^^^^ ^^^^^^^^^

error: aborting due to 2 previous errors

Some errors occurred: E0107, E0191.
For more information about an error, try `rustc --explain E0107`.
2 changes: 1 addition & 1 deletion src/test/ui/traits/trait-alias-object.stderr
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ error[E0191]: the value of the associated type `Item` (from the trait `std::iter
--> $DIR/trait-alias-object.rs:18:13
|
LL | let _: &dyn IteratorAlias = &vec![123].into_iter();
| ^^^^^^^^^^^^^^^^^ missing associated type `Item` value
| ^^^^^^^^^^^^^^^^^ associated type `Item` must be specified

error: aborting due to 2 previous errors