about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2021-03-18 03:02:44 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2021-03-18 03:02:44 +0300
commitb48530bf8b30c20a75f5bb7c2021a28c0ae40413 (patch)
treedb152e7a46d3af4eb0cf74a4161ffdce0121ca5e /compiler
parent38ed36bba4669a3a6737d1f973789a459b8530b2 (diff)
downloadrust-b48530bf8b30c20a75f5bb7c2021a28c0ae40413.tar.gz
rust-b48530bf8b30c20a75f5bb7c2021a28c0ae40413.zip
Report missing cases of `bare_trait_objects`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs34
2 files changed, 34 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index d0a03008c95..7c5398003f3 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 20fe0c1471c..dc8a804bfea 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!("<dyn ({})>", s), Applicability::MachineApplicable)
+                        }
+                        Ok(s) => (format!("<dyn {}>", s), Applicability::MachineApplicable),
+                        Err(_) => ("<dyn <type>>".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,