From b48530bf8b30c20a75f5bb7c2021a28c0ae40413 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 18 Mar 2021 03:02:44 +0300 Subject: [PATCH] Report missing cases of `bare_trait_objects` --- compiler/rustc_typeck/src/astconv/mod.rs | 2 ++ .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 34 +++++++++++++++++-- src/test/ui/lint/bare-trait-objects-path.rs | 18 ++++++++++ .../ui/lint/bare-trait-objects-path.stderr | 29 ++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/lint/bare-trait-objects-path.rs create mode 100644 src/test/ui/lint/bare-trait-objects-path.stderr diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index d0a03008c9522..7c5398003f3e6 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1608,6 +1608,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // the whole path. // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type // parameter or `Self`. + // NOTE: When this function starts resolving `Trait::AssocTy` successfully + // it should also start reportint the `BARE_TRAIT_OBJECTS` lint. pub fn associated_path_to_ty( &self, hir_ref_id: hir::HirId, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 20fe0c1471c9c..dc8a804bfea98 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -6,6 +6,7 @@ use crate::check::callee::{self, DeferredCallResolution}; use crate::check::method::{self, MethodCallee, SelfSource}; use crate::check::{BreakableCtxt, Diverges, Expectation, FallbackMode, FnCtxt, LocalTy}; +use rustc_ast::TraitObjectSyntax; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported}; @@ -13,7 +14,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, GenericArg, Node, QPath}; +use rustc_hir::{ExprKind, GenericArg, Node, QPath, TyKind}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::{InferOk, InferResult}; @@ -26,7 +27,9 @@ use rustc_middle::ty::{ self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, ToPolyTraitRef, ToPredicate, Ty, UserType, }; -use rustc_session::{lint, parse::feature_err}; +use rustc_session::lint; +use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS; +use rustc_session::parse::feature_err; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{self, BytePos, MultiSpan, Span}; @@ -947,6 +950,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { result }); + if result.is_ok() { + self.maybe_lint_bare_trait(qpath, hir_id); + } + // Write back the new resolution. self.write_resolution(hir_id, result); ( @@ -956,6 +963,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } + fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId) { + if let QPath::TypeRelative(self_ty, _) = qpath { + if let TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = + self_ty.kind + { + self.tcx.struct_span_lint_hir(BARE_TRAIT_OBJECTS, hir_id, self_ty.span, |lint| { + let mut db = lint + .build(&format!("trait objects without an explicit `dyn` are deprecated")); + let (sugg, app) = match self.tcx.sess.source_map().span_to_snippet(self_ty.span) + { + Ok(s) if poly_trait_ref.trait_ref.path.is_global() => { + (format!("", s), Applicability::MachineApplicable) + } + Ok(s) => (format!("", s), Applicability::MachineApplicable), + Err(_) => (">".to_string(), Applicability::HasPlaceholders), + }; + db.span_suggestion(self_ty.span, "use `dyn`", sugg, app); + db.emit() + }); + } + } + } + /// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise. pub(in super::super) fn get_node_fn_decl( &self, diff --git a/src/test/ui/lint/bare-trait-objects-path.rs b/src/test/ui/lint/bare-trait-objects-path.rs new file mode 100644 index 0000000000000..4c961e998df64 --- /dev/null +++ b/src/test/ui/lint/bare-trait-objects-path.rs @@ -0,0 +1,18 @@ +#![feature(associated_type_defaults)] + +trait Assoc { + fn func() {} + const CONST: u8 = 0; + type Ty = u8; +} + +trait Dyn {} + +impl Assoc for dyn Dyn {} + +fn main() { + Dyn::func(); //~ WARN trait objects without an explicit `dyn` are deprecated + ::Dyn::func(); //~ WARN trait objects without an explicit `dyn` are deprecated + Dyn::CONST; //~ WARN trait objects without an explicit `dyn` are deprecated + let _: Dyn::Ty; //~ ERROR ambiguous associated type +} diff --git a/src/test/ui/lint/bare-trait-objects-path.stderr b/src/test/ui/lint/bare-trait-objects-path.stderr new file mode 100644 index 0000000000000..0a2dc5858285a --- /dev/null +++ b/src/test/ui/lint/bare-trait-objects-path.stderr @@ -0,0 +1,29 @@ +error[E0223]: ambiguous associated type + --> $DIR/bare-trait-objects-path.rs:17:12 + | +LL | let _: Dyn::Ty; + | ^^^^^^^ help: use fully-qualified syntax: `::Ty` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:14:5 + | +LL | Dyn::func(); + | ^^^ help: use `dyn`: `` + | + = note: `#[warn(bare_trait_objects)]` on by default + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:15:5 + | +LL | ::Dyn::func(); + | ^^^^^ help: use `dyn`: `` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:16:5 + | +LL | Dyn::CONST; + | ^^^ help: use `dyn`: `` + +error: aborting due to previous error; 3 warnings emitted + +For more information about this error, try `rustc --explain E0223`.