about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/entry.rs26
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs9
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs8
-rw-r--r--compiler/rustc_passes/messages.ftl6
-rw-r--r--compiler/rustc_passes/src/entry.rs42
-rw-r--r--compiler/rustc_passes/src/errors.rs16
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs29
10 files changed, 79 insertions, 77 deletions
diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs
index cd8a5a66920..dd231e286d5 100644
--- a/compiler/rustc_ast/src/entry.rs
+++ b/compiler/rustc_ast/src/entry.rs
@@ -4,11 +4,35 @@ use rustc_span::Symbol;
 
 #[derive(Debug)]
 pub enum EntryPointType {
+    /// This function is not an entrypoint.
     None,
+    /// This is a function called `main` at the root level.
+    /// ```
+    /// fn main() {}
+    /// ```
     MainNamed,
+    /// This is a function with the `#[rustc_main]` attribute.
+    /// Used by the testing harness to create the test entrypoint.
+    /// ```ignore (clashes with test entrypoint)
+    /// #[rustc_main]
+    /// fn main() {}
+    /// ```
     RustcMainAttr,
+    /// This is a function with the `#[start]` attribute.
+    /// ```ignore (clashes with test entrypoint)
+    /// #[start]
+    /// fn main() {}
+    /// ```
     Start,
-    OtherMain, // Not an entry point, but some other function named main
+    /// This function is **not** an entrypoint but simply named `main` (not at the root).
+    /// This is only used for diagnostics.
+    /// ```
+    /// #[allow(dead_code)]
+    /// mod meow {
+    ///     fn main() {}
+    /// }
+    /// ```
+    OtherMain,
 }
 
 pub fn entry_point_type(
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index a2015445b42..8cf431482ff 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -266,7 +266,7 @@ fn generate_test_harness(
 ///
 /// By default this expands to
 ///
-/// ```ignore UNSOLVED (I think I still need guidance for this one. Is it correct? Do we try to make it run? How do we nicely fill it out?)
+/// ```ignore (messes with test internals)
 /// #[rustc_main]
 /// pub fn main() {
 ///     extern crate test;
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index e9cf5a3d769..6e6fa70107b 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -467,19 +467,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         let intrinsic_name = ecx.tcx.item_name(instance.def_id());
 
         // CTFE-specific intrinsics.
-        let Some(ret) = target else {
-            // Handle diverging intrinsics. We can't handle any of them (that are not already
-            // handled above), but check if there is a fallback body.
-            if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
-                throw_unsup_format!(
-                    "intrinsic `{intrinsic_name}` is not supported at compile-time"
-                );
-            }
-            return Ok(Some(ty::Instance {
-                def: ty::InstanceDef::Item(instance.def_id()),
-                args: instance.args,
-            }));
-        };
         match intrinsic_name {
             sym::ptr_guaranteed_cmp => {
                 let a = ecx.read_scalar(&args[0])?;
@@ -559,7 +546,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
             }
         }
 
-        ecx.go_to_block(ret);
+        // Intrinsic is done, jump to next block.
+        ecx.return_to_block(target)?;
         Ok(None)
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index f73293856c7..88ce5a7cbeb 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -113,10 +113,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, bool> {
         let instance_args = instance.args;
         let intrinsic_name = self.tcx.item_name(instance.def_id());
-        let Some(ret) = ret else {
-            // We don't support any intrinsic without return place.
-            return Ok(false);
-        };
 
         match intrinsic_name {
             sym::caller_location => {
@@ -376,7 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     };
 
                     M::panic_nounwind(self, &msg)?;
-                    // Skip the `go_to_block` at the end.
+                    // Skip the `return_to_block` at the end (we panicked, we do not return).
                     return Ok(true);
                 }
             }
@@ -437,11 +433,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
             }
 
+            // Unsupported intrinsic: skip the return_to_block below.
             _ => return Ok(false),
         }
 
         trace!("{:?}", self.dump_place(&dest.clone().into()));
-        self.go_to_block(ret);
+        self.return_to_block(ret)?;
         Ok(true)
     }
 
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 9c33cc8ed0b..dbb88e42a3e 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -518,7 +518,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // RFC 2397
     gated!(
         do_not_recommend, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, experimental!(do_not_recommend)
+        EncodeCrossCrate::Yes, experimental!(do_not_recommend)
     ),
 
     // `#[cfi_encoding = ""]`
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index e9a6276192e..3c423b4e2aa 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -164,9 +164,9 @@ pub(super) fn unexpected_cfg_name(
 
     if is_from_cargo {
         if !is_feature_cfg {
-            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
+            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`"));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration");
     } else {
         diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
         diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
@@ -266,9 +266,9 @@ pub(super) fn unexpected_cfg_value(
                 diag.help("consider defining some features in `Cargo.toml`");
             }
         } else if !is_cfg_a_well_know_name {
-            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
+            diag.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo::rustc-check-cfg={inst}\");` to the top of the `build.rs`"));
         }
-        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
+        diag.note("see <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg> for more information about checking conditional configuration");
     } else {
         if !is_cfg_a_well_know_name {
             diag.help(format!("to expect this configuration use `--check-cfg={inst}`"));
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 8878310d6e9..9d58d301e2b 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -49,12 +49,6 @@ passes_attr_crate_level =
 passes_attr_only_in_functions =
     `{$attr}` attribute can only be used on functions
 
-passes_attr_only_on_main =
-    `{$attr}` attribute can only be used on `fn main()`
-
-passes_attr_only_on_root_main =
-    `{$attr}` attribute can only be used on root `fn main()`
-
 passes_both_ffi_const_and_pure =
     `#[ffi_const]` function cannot be `#[ffi_pure]`
 
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index d52092f2aa9..b43c8282db1 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -18,10 +18,10 @@ use crate::errors::{
 struct EntryContext<'tcx> {
     tcx: TyCtxt<'tcx>,
 
-    /// The function that has attribute named `main`.
-    attr_main_fn: Option<(LocalDefId, Span)>,
+    /// The function has the `#[rustc_main]` attribute.
+    rustc_main_fn: Option<(LocalDefId, Span)>,
 
-    /// The function that has the attribute 'start' on it.
+    /// The function that has the attribute `#[start]` on it.
     start_fn: Option<(LocalDefId, Span)>,
 
     /// The functions that one might think are `main` but aren't, e.g.
@@ -42,10 +42,10 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
     }
 
     let mut ctxt =
-        EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
+        EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
 
     for id in tcx.hir().items() {
-        find_item(id, &mut ctxt);
+        check_and_search_item(id, &mut ctxt);
     }
 
     configure_main(tcx, &ctxt)
@@ -56,7 +56,16 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti
     attr::find_by_name(attrs, sym).map(|attr| attr.span)
 }
 
-fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
+fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
+    if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) {
+        for attr in [sym::start, sym::rustc_main] {
+            if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
+                ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
+            }
+        }
+        return;
+    }
+
     let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
 
     let attrs = ctxt.tcx.hir().attrs(id.hir_id());
@@ -65,26 +74,20 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
         at_root,
         ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
     );
+
     match entry_point_type {
-        EntryPointType::None => (),
-        _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
-            for attr in [sym::start, sym::rustc_main] {
-                if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
-                    ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
-                }
-            }
-        }
-        EntryPointType::MainNamed => (),
+        EntryPointType::None => {}
+        EntryPointType::MainNamed => {}
         EntryPointType::OtherMain => {
             ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
         }
         EntryPointType::RustcMainAttr => {
-            if ctxt.attr_main_fn.is_none() {
-                ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
+            if ctxt.rustc_main_fn.is_none() {
+                ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
             } else {
                 ctxt.tcx.dcx().emit_err(MultipleRustcMain {
                     span: ctxt.tcx.def_span(id.owner_id.to_def_id()),
-                    first: ctxt.attr_main_fn.unwrap().1,
+                    first: ctxt.rustc_main_fn.unwrap().1,
                     additional: ctxt.tcx.def_span(id.owner_id.to_def_id()),
                 });
             }
@@ -107,10 +110,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
 fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
     if let Some((def_id, _)) = visitor.start_fn {
         Some((def_id.to_def_id(), EntryFnType::Start))
-    } else if let Some((local_def_id, _)) = visitor.attr_main_fn {
+    } else if let Some((local_def_id, _)) = visitor.rustc_main_fn {
         let def_id = local_def_id.to_def_id();
         Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }))
     } else {
+        // The actual resolution of main happens in the resolver, this here
         if let Some(main_def) = tcx.resolutions(()).main_def
             && let Some(def_id) = main_def.opt_fn_def_id()
         {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 743faf54560..65cad82cc8c 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1207,22 +1207,6 @@ pub struct NakedFunctionsMustUseNoreturn {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_attr_only_on_main)]
-pub struct AttrOnlyOnMain {
-    #[primary_span]
-    pub span: Span,
-    pub attr: Symbol,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_attr_only_on_root_main)]
-pub struct AttrOnlyOnRootMain {
-    #[primary_span]
-    pub span: Span,
-    pub attr: Symbol,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_attr_only_in_functions)]
 pub struct AttrOnlyInFunctions {
     #[primary_span]
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 796222129f1..fd4b5805f02 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -11,6 +11,7 @@ use rustc_infer::traits::{
 };
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::symbol::sym;
 
 use super::eval_ctxt::GenerateProofTree;
 use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
@@ -137,7 +138,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             .collect();
 
         errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
-            obligation: find_best_leaf_obligation(infcx, &obligation),
+            obligation: find_best_leaf_obligation(infcx, &obligation, true),
             code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
             root_obligation: obligation,
         }));
@@ -198,7 +199,7 @@ fn fulfillment_error_for_no_solution<'tcx>(
     infcx: &InferCtxt<'tcx>,
     root_obligation: PredicateObligation<'tcx>,
 ) -> FulfillmentError<'tcx> {
-    let obligation = find_best_leaf_obligation(infcx, &root_obligation);
+    let obligation = find_best_leaf_obligation(infcx, &root_obligation, false);
 
     let code = match obligation.predicate.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
@@ -266,7 +267,7 @@ fn fulfillment_error_for_stalled<'tcx>(
     });
 
     FulfillmentError {
-        obligation: find_best_leaf_obligation(infcx, &obligation),
+        obligation: find_best_leaf_obligation(infcx, &obligation, true),
         code,
         root_obligation: obligation,
     }
@@ -275,12 +276,13 @@ fn fulfillment_error_for_stalled<'tcx>(
 fn find_best_leaf_obligation<'tcx>(
     infcx: &InferCtxt<'tcx>,
     obligation: &PredicateObligation<'tcx>,
+    consider_ambiguities: bool,
 ) -> PredicateObligation<'tcx> {
     let obligation = infcx.resolve_vars_if_possible(obligation.clone());
     infcx
         .visit_proof_tree(
             obligation.clone().into(),
-            &mut BestObligation { obligation: obligation.clone() },
+            &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
         )
         .break_value()
         .unwrap_or(obligation)
@@ -288,6 +290,7 @@ fn find_best_leaf_obligation<'tcx>(
 
 struct BestObligation<'tcx> {
     obligation: PredicateObligation<'tcx>,
+    consider_ambiguities: bool,
 }
 
 impl<'tcx> BestObligation<'tcx> {
@@ -320,6 +323,14 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             return ControlFlow::Break(self.obligation.clone());
         };
 
+        // Don't walk into impls that have `do_not_recommend`.
+        if let ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } =
+            candidate.kind()
+            && goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend)
+        {
+            return ControlFlow::Break(self.obligation.clone());
+        }
+
         // FIXME: Could we extract a trait ref from a projection here too?
         // FIXME: Also, what about considering >1 layer up the stack? May be necessary
         // for normalizes-to.
@@ -355,11 +366,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                 }
             }
 
-            // Skip nested goals that hold.
-            //FIXME: We should change the max allowed certainty based on if we're
-            // visiting an ambiguity or error obligation.
-            if matches!(nested_goal.result(), Ok(Certainty::Yes)) {
-                continue;
+            // Skip nested goals that aren't the *reason* for our goal's failure.
+            match self.consider_ambiguities {
+                true if matches!(nested_goal.result(), Ok(Certainty::Maybe(_))) => {}
+                false if matches!(nested_goal.result(), Err(_)) => {}
+                _ => continue,
             }
 
             self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;