about summary refs log tree commit diff
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
parent38ed36bba4669a3a6737d1f973789a459b8530b2 (diff)
downloadrust-b48530bf8b30c20a75f5bb7c2021a28c0ae40413.tar.gz
rust-b48530bf8b30c20a75f5bb7c2021a28c0ae40413.zip
Report missing cases of `bare_trait_objects`
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs34
-rw-r--r--src/test/ui/lint/bare-trait-objects-path.rs18
-rw-r--r--src/test/ui/lint/bare-trait-objects-path.stderr29
4 files changed, 81 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,
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 00000000000..4c961e998df
--- /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 00000000000..0a2dc585828
--- /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: `<dyn Dyn as Trait>::Ty`
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/bare-trait-objects-path.rs:14:5
+   |
+LL |     Dyn::func();
+   |     ^^^ help: use `dyn`: `<dyn 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`: `<dyn (::Dyn)>`
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/bare-trait-objects-path.rs:16:5
+   |
+LL |     Dyn::CONST;
+   |     ^^^ help: use `dyn`: `<dyn Dyn>`
+
+error: aborting due to previous error; 3 warnings emitted
+
+For more information about this error, try `rustc --explain E0223`.