diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 20b9ed9cd7356..d290752614c29 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -334,7 +334,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut local_visitor = FindInferSourceVisitor::new(&self, typeck_results, arg); if let Some(body_id) = body_id { let expr = self.tcx.hir().expect_expr(body_id.hir_id); - debug!(?expr); local_visitor.visit_expr(expr); } @@ -550,6 +549,7 @@ impl<'tcx> InferSourceKind<'tcx> { } } +#[derive(Debug)] struct InsertableGenericArgs<'tcx> { insert_span: Span, substs: SubstsRef<'tcx>, @@ -735,10 +735,20 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { return self.path_inferred_subst_iter(expr.hir_id, substs, path); } } - hir::ExprKind::Struct(path, _, _) => { + // FIXME(#98711): Ideally we would also deal with type relative + // paths here, even if that is quite rare. + // + // See the `need_type_info/expr-struct-type-relative-gat.rs` test + // for an example where that would be needed. + // + // However, the `type_dependent_def_id` for `Self::Output` in an + // impl is currently the `DefId` of `Output` in the trait definition + // which makes this somewhat difficult and prevents us from just + // using `self.path_inferred_subst_iter` here. + hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _) => { if let Some(ty) = self.opt_node_type(expr.hir_id) { if let ty::Adt(_, substs) = ty.kind() { - return self.path_inferred_subst_iter(expr.hir_id, substs, path); + return Box::new(self.resolved_path_inferred_subst_iter(path, substs)); } } } @@ -945,6 +955,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { intravisit::walk_body(self, body); } + #[instrument(level = "debug", skip(self))] fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { let tcx = self.infcx.tcx; match expr.kind { @@ -959,9 +970,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { _ => intravisit::walk_expr(self, expr), } - for InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } in - self.expr_inferred_subst_iter(expr) - { + for args in self.expr_inferred_subst_iter(expr) { + debug!(?args); + let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args; let generics = tcx.generics_of(generics_def_id); if let Some(argument_index) = generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg)) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index ea7ebdf91d012..9ef5f331aaa5c 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -156,6 +156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().field_indices_mut().insert(hir_id, index); } + #[instrument(level = "debug", skip(self))] pub(in super::super) fn write_resolution( &self, hir_id: hir::HirId, @@ -164,8 +165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().type_dependent_defs_mut().insert(hir_id, r); } + #[instrument(level = "debug", skip(self))] pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { - debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method); self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_substs(hir_id, method.substs); diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs new file mode 100644 index 0000000000000..42af9fa8d113a --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.rs @@ -0,0 +1,21 @@ +trait Foo { + type Output; + + fn baz() -> Self::Output; +} + +fn needs_infer() {} + +enum Bar { + Variant {} +} + +impl Foo for u8 { + type Output = Bar; + fn baz() -> Self::Output { + needs_infer(); //~ ERROR type annotations needed + Self::Output::Variant {} + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr new file mode 100644 index 0000000000000..68ecb38134837 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative-enum.rs:16:9 + | +LL | needs_infer(); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer` + | +help: consider specifying the generic argument + | +LL | needs_infer::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs new file mode 100644 index 0000000000000..bcd29bb4e3495 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.rs @@ -0,0 +1,21 @@ +#![feature(generic_associated_types)] + +trait Foo { + type Output; + + fn baz(); +} + +enum Bar { + Simple {}, + Generic(T), +} + +impl Foo for u8 { + type Output = Bar; + fn baz() { + Self::Output::Simple {}; //~ ERROR type annotations needed + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr new file mode 100644 index 0000000000000..65a75b68c1f08 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative-gat.rs:17:9 + | +LL | Self::Output::Simple {}; + | ^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated type `Output` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs b/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs new file mode 100644 index 0000000000000..c3ece2b16cf08 --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative.rs @@ -0,0 +1,21 @@ +// regression test for #98598 + +trait Foo { + type Output; + + fn baz() -> Self::Output; +} + +fn needs_infer() {} + +struct Bar {} + +impl Foo for u8 { + type Output = Bar; + fn baz() -> Self::Output { + needs_infer(); //~ ERROR type annotations needed + Self::Output {} + } +} + +fn main() {} diff --git a/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr b/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr new file mode 100644 index 0000000000000..397d8e7be04ff --- /dev/null +++ b/src/test/ui/inference/need_type_info/expr-struct-type-relative.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative.rs:16:9 + | +LL | needs_infer(); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer` + | +help: consider specifying the generic argument + | +LL | needs_infer::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`.