Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #132919

Merged
merged 18 commits into from
Nov 12, 2024
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ecfcd08
Arbitrary self types v2: (unused) Receiver trait
adetaylor Oct 25, 2024
bb0b2ab
Make sure all expr checking fns start with check_expr
compiler-errors Oct 29, 2024
2deb5fd
Stop passing two optional pieces of data disjointly
compiler-errors Oct 29, 2024
86da250
Document some check_expr methods
compiler-errors Oct 29, 2024
33f500d
Add Set entry API
SUPERCILEX Jan 18, 2024
cb44c0c
Add a default implementation for CodegenBackend::link
bjorn3 Nov 9, 2024
0a619db
Pass owned CodegenResults to link_binary
bjorn3 Nov 9, 2024
e8b1029
Fix error message for direct usage of sess.opts.crate_types
bjorn3 Nov 9, 2024
bab112c
triagebot: Autolabel rustdoc book
aDotInTheVoid Nov 10, 2024
0a88d51
Unvacation fmease
fmease Nov 11, 2024
d0ddba3
Simplify some places that deal with generic parameter defaults
fmease Nov 11, 2024
3ab4477
Rollup merge of #120077 - SUPERCILEX:set-entry, r=Amanieu
matthiaskrgr Nov 11, 2024
9d7facc
Rollup merge of #132144 - adetaylor:receiver-trait-itself, r=wesleywiser
matthiaskrgr Nov 11, 2024
517e8be
Rollup merge of #132297 - compiler-errors:check-expr-tweaks, r=lcnr
matthiaskrgr Nov 11, 2024
35225d6
Rollup merge of #132820 - bjorn3:default_backend_link_impl, r=jieyouxu
matthiaskrgr Nov 11, 2024
f344169
Rollup merge of #132881 - aDotInTheVoid:docs-for-docs, r=jieyouxu
matthiaskrgr Nov 11, 2024
b41baf8
Rollup merge of #132912 - fmease:simplify-gen-param-default-users, r=…
matthiaskrgr Nov 11, 2024
2d02652
Rollup merge of #132916 - fmease:unvac-me, r=fmease
matthiaskrgr Nov 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions compiler/rustc_codegen_cranelift/src/archive.rs

This file was deleted.

13 changes: 0 additions & 13 deletions compiler/rustc_codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
@@ -43,7 +43,6 @@ use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_ssa::back::versioned_llvm_target;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_errors::ErrorGuaranteed;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::Session;
@@ -56,7 +55,6 @@ use crate::prelude::*;
mod abi;
mod allocator;
mod analyze;
mod archive;
mod base;
mod cast;
mod codegen_i128;
@@ -249,17 +247,6 @@ impl CodegenBackend for CraneliftCodegenBackend {
self.config.borrow().as_ref().unwrap(),
)
}

fn link(
&self,
sess: &Session,
codegen_results: CodegenResults,
outputs: &OutputFilenames,
) -> Result<(), ErrorGuaranteed> {
use rustc_codegen_ssa::back::link::link_binary;

link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs)
}
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
25 changes: 0 additions & 25 deletions compiler/rustc_codegen_gcc/src/archive.rs

This file was deleted.

14 changes: 1 addition & 13 deletions compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -58,7 +58,6 @@ extern crate rustc_driver;

mod abi;
mod allocator;
mod archive;
mod asm;
mod attributes;
mod back;
@@ -103,7 +102,7 @@ use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBacken
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed};
use rustc_errors::DiagCtxtHandle;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
@@ -261,17 +260,6 @@ impl CodegenBackend for GccCodegenBackend {
.join(sess)
}

fn link(
&self,
sess: &Session,
codegen_results: CodegenResults,
outputs: &OutputFilenames,
) -> Result<(), ErrorGuaranteed> {
use rustc_codegen_ssa::back::link::link_binary;

link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs)
}

fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
target_features(sess, allow_unstable, &self.target_info)
}
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -382,7 +382,7 @@ impl CodegenBackend for LlvmCodegenBackend {

// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs)
link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, outputs)
}
}

8 changes: 8 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
@@ -304,6 +304,14 @@ pub trait ArchiveBuilder {
fn build(self: Box<Self>, output: &Path) -> bool;
}

pub struct ArArchiveBuilderBuilder;

impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER))
}
}

#[must_use = "must call build() to finish building the archive"]
pub struct ArArchiveBuilder<'a> {
sess: &'a Session,
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
@@ -69,7 +69,7 @@ pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
pub fn link_binary(
sess: &Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
codegen_results: &CodegenResults,
codegen_results: CodegenResults,
outputs: &OutputFilenames,
) -> Result<(), ErrorGuaranteed> {
let _timer = sess.timer("link_binary");
@@ -116,7 +116,7 @@ pub fn link_binary(
link_rlib(
sess,
archive_builder_builder,
codegen_results,
&codegen_results,
RlibFlavor::Normal,
&path,
)?
@@ -126,7 +126,7 @@ pub fn link_binary(
link_staticlib(
sess,
archive_builder_builder,
codegen_results,
&codegen_results,
&out_filename,
&path,
)?;
@@ -137,7 +137,7 @@ pub fn link_binary(
archive_builder_builder,
crate_type,
&out_filename,
codegen_results,
&codegen_results,
path.as_ref(),
)?;
}
6 changes: 5 additions & 1 deletion compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ use rustc_span::symbol::Symbol;

use super::CodegenObject;
use super::write::WriteBackendMethods;
use crate::back::archive::ArArchiveBuilderBuilder;
use crate::back::link::link_binary;
use crate::back::write::TargetMachineFactoryFn;
use crate::{CodegenResults, ModuleCodegen};

@@ -87,7 +89,9 @@ pub trait CodegenBackend {
sess: &Session,
codegen_results: CodegenResults,
outputs: &OutputFilenames,
) -> Result<(), ErrorGuaranteed>;
) -> Result<(), ErrorGuaranteed> {
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs)
}

/// Returns `true` if this backend can be safely called from multiple threads.
///
2 changes: 2 additions & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
@@ -241,6 +241,8 @@ language_item_table! {
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0);
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None;
LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None;

Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
98 changes: 23 additions & 75 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -1427,57 +1427,28 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let predicates = tcx.predicates_of(def_id.to_def_id());
let generics = tcx.generics_of(def_id);

let is_our_default = |def: &ty::GenericParamDef| match def.kind {
GenericParamDefKind::Type { has_default, .. }
| GenericParamDefKind::Const { has_default, .. } => {
has_default && def.index >= generics.parent_count as u32
}
GenericParamDefKind::Lifetime => {
span_bug!(tcx.def_span(def.def_id), "lifetime params can have no default")
}
};

// Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
// For example, this forbids the declaration:
//
// struct Foo<T = Vec<[u32]>> { .. }
//
// Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
for param in &generics.own_params {
match param.kind {
GenericParamDefKind::Type { .. } => {
if is_our_default(param) {
let ty = tcx.type_of(param.def_id).instantiate_identity();
// Ignore dependent defaults -- that is, where the default of one type
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
if !ty.has_param() {
wfcx.register_wf_obligation(
tcx.def_span(param.def_id),
Some(WellFormedLoc::Ty(param.def_id.expect_local())),
ty.into(),
);
}
}
}
GenericParamDefKind::Const { .. } => {
if is_our_default(param) {
// FIXME(const_generics_defaults): This
// is incorrect when dealing with unused args, for example
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
// we should eagerly error.
let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
if !default_ct.has_param() {
wfcx.register_wf_obligation(
tcx.def_span(param.def_id),
None,
default_ct.into(),
);
}
}
if let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity) {
// Ignore dependent defaults -- that is, where the default of one type
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
// FIXME(generic_const_exprs): This is incorrect when dealing with unused const params.
// E.g: `struct Foo<const N: usize, const M: usize = { 1 - 2 }>;`. Here, we should
// eagerly error but we don't as we have `ConstKind::Unevaluated(.., [N, M])`.
if !default.has_param() {
wfcx.register_wf_obligation(
tcx.def_span(param.def_id),
matches!(param.kind, GenericParamDefKind::Type { .. })
.then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
default,
);
}
// Doesn't have defaults.
GenericParamDefKind::Lifetime => {}
}
}

@@ -1490,39 +1461,16 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
//
// First we build the defaulted generic parameters.
let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
// All regions are identity.
tcx.mk_param_from_def(param)
}

GenericParamDefKind::Type { .. } => {
// If the param has a default, ...
if is_our_default(param) {
let default_ty = tcx.type_of(param.def_id).instantiate_identity();
// ... and it's not a dependent default, ...
if !default_ty.has_param() {
// ... then instantiate it with the default.
return default_ty.into();
}
}

tcx.mk_param_from_def(param)
}
GenericParamDefKind::Const { .. } => {
// If the param has a default, ...
if is_our_default(param) {
let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
// ... and it's not a dependent default, ...
if !default_ct.has_param() {
// ... then instantiate it with the default.
return default_ct.into();
}
}

tcx.mk_param_from_def(param)
}
if param.index >= generics.parent_count as u32
// If the param has a default, ...
&& let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity)
// ... and it's not a dependent default, ...
&& !default.has_param()
{
// ... then instantiate it with the default.
return default;
}
tcx.mk_param_from_def(param)
});

// Now we build the instantiated predicates.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ use crate::{Diverges, Expectation, FnCtxt, Needs};

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[instrument(skip(self), level = "debug", ret)]
pub(crate) fn check_match(
pub(crate) fn check_expr_match(
&self,
expr: &'tcx hir::Expr<'tcx>,
scrut: &'tcx hir::Expr<'tcx>,
5 changes: 2 additions & 3 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ enum CallStep<'tcx> {
}

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn check_call(
pub(crate) fn check_expr_call(
&self,
call_expr: &'tcx hir::Expr<'tcx>,
callee_expr: &'tcx hir::Expr<'tcx>,
@@ -74,8 +74,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.check_expr_with_expectation_and_args(
callee_expr,
Expectation::NoExpectation,
arg_exprs,
Some(call_expr),
Some((call_expr, arg_exprs)),
),
_ => self.check_expr(callee_expr),
};
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/check.rs
Original file line number Diff line number Diff line change
@@ -137,7 +137,7 @@ pub(super) fn check_fn<'a, 'tcx>(
}

fcx.is_whole_body.set(true);
fcx.check_return_expr(body.value, false);
fcx.check_return_or_body_tail(body.value, false);

// Finalize the return check by taking the LUB of the return types
// we saw and assigning it to the expected return type. This isn't
95 changes: 53 additions & 42 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
@@ -55,6 +55,9 @@ use crate::{
};

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Check an expr with an expectation type, and also demand that the expr's
/// evaluated type is a subtype of the expectation at the end. This is a
/// *hard* requirement.
pub(crate) fn check_expr_has_type_or_error(
&self,
expr: &'tcx hir::Expr<'tcx>,
@@ -97,6 +100,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty
}

/// Check an expr with an expectation type, and also demand that the expr's
/// evaluated type is a coercible to the expectation at the end. This is a
/// *hard* requirement.
pub(super) fn check_expr_coercible_to_type(
&self,
expr: &'tcx hir::Expr<'tcx>,
@@ -128,6 +134,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

/// Check an expr with an expectation type. Don't actually enforce that expectation
/// is related to the expr's evaluated type via subtyping or coercion. This is
/// usually called because we want to do that subtype/coerce call manually for better
/// diagnostics.
pub(super) fn check_expr_with_hint(
&self,
expr: &'tcx hir::Expr<'tcx>,
@@ -136,6 +146,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr_with_expectation(expr, ExpectHasType(expected))
}

/// Check an expr with an expectation type, and also [`Needs`] which will
/// prompt typeck to convert any implicit immutable derefs to mutable derefs.
fn check_expr_with_expectation_and_needs(
&self,
expr: &'tcx hir::Expr<'tcx>,
@@ -153,10 +165,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty
}

/// Check an expr with no expectations.
pub(super) fn check_expr(&self, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> {
self.check_expr_with_expectation(expr, NoExpectation)
}

/// Check an expr with no expectations, but with [`Needs`] which will
/// prompt typeck to convert any implicit immutable derefs to mutable derefs.
pub(super) fn check_expr_with_needs(
&self,
expr: &'tcx hir::Expr<'tcx>,
@@ -165,33 +180,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr_with_expectation_and_needs(expr, NoExpectation, needs)
}

/// Invariant:
/// If an expression has any sub-expressions that result in a type error,
/// inspecting that expression's type with `ty.references_error()` will return
/// true. Likewise, if an expression is known to diverge, inspecting its
/// type with `ty::type_is_bot` will return true (n.b.: since Rust is
/// strict, _|_ can appear in the type of an expression that does not,
/// itself, diverge: for example, fn() -> _|_.)
/// Note that inspecting a type's structure *directly* may expose the fact
/// that there are actually multiple representations for `Error`, so avoid
/// that when err needs to be handled differently.
/// Check an expr with an expectation type which may be used to eagerly
/// guide inference when evaluating that expr.
#[instrument(skip(self, expr), level = "debug")]
pub(super) fn check_expr_with_expectation(
&self,
expr: &'tcx hir::Expr<'tcx>,
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
self.check_expr_with_expectation_and_args(expr, expected, &[], None)
self.check_expr_with_expectation_and_args(expr, expected, None)
}

/// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
/// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
/// Same as [`Self::check_expr_with_expectation`], but allows us to pass in
/// the arguments of a [`ExprKind::Call`] when evaluating its callee that
/// is an [`ExprKind::Path`]. We use this to refine the spans for certain
/// well-formedness guarantees for the path expr.
pub(super) fn check_expr_with_expectation_and_args(
&self,
expr: &'tcx hir::Expr<'tcx>,
expected: Expectation<'tcx>,
args: &'tcx [hir::Expr<'tcx>],
call: Option<&'tcx hir::Expr<'tcx>>,
call_expr_and_args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
) -> Ty<'tcx> {
if self.tcx().sess.verbose_internals() {
// make this code only run with -Zverbose-internals because it is probably slow
@@ -236,9 +244,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

let ty = ensure_sufficient_stack(|| match &expr.kind {
// Intercept the callee path expr and give it better spans.
hir::ExprKind::Path(
qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)),
) => self.check_expr_path(qpath, expr, Some(args), call),
) => self.check_expr_path(qpath, expr, call_expr_and_args),
_ => self.check_expr_kind(expr, expected),
});
let ty = self.resolve_vars_if_possible(ty);
@@ -472,28 +481,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let tcx = self.tcx;
match expr.kind {
ExprKind::Lit(ref lit) => self.check_lit(lit, expected),
ExprKind::Binary(op, lhs, rhs) => self.check_binop(expr, op, lhs, rhs, expected),
ExprKind::Lit(ref lit) => self.check_expr_lit(lit, expected),
ExprKind::Binary(op, lhs, rhs) => self.check_expr_binop(expr, op, lhs, rhs, expected),
ExprKind::Assign(lhs, rhs, span) => {
self.check_expr_assign(expr, expected, lhs, rhs, span)
}
ExprKind::AssignOp(op, lhs, rhs) => {
self.check_binop_assign(expr, op, lhs, rhs, expected)
self.check_expr_binop_assign(expr, op, lhs, rhs, expected)
}
ExprKind::Unary(unop, oprnd) => self.check_expr_unary(unop, oprnd, expected, expr),
ExprKind::Unary(unop, oprnd) => self.check_expr_unop(unop, oprnd, expected, expr),
ExprKind::AddrOf(kind, mutbl, oprnd) => {
self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
}
ExprKind::Path(QPath::LangItem(lang_item, _)) => {
self.check_lang_item_path(lang_item, expr)
}
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, None, None),
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, None),
ExprKind::InlineAsm(asm) => {
// We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
self.check_expr_asm(asm)
}
ExprKind::OffsetOf(container, fields) => self.check_offset_of(container, fields, expr),
ExprKind::OffsetOf(container, fields) => {
self.check_expr_offset_of(container, fields, expr)
}
ExprKind::Break(destination, ref expr_opt) => {
self.check_expr_break(destination, expr_opt.as_deref(), expr)
}
@@ -512,13 +523,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr_loop(body, source, expected, expr)
}
ExprKind::Match(discrim, arms, match_src) => {
self.check_match(expr, discrim, arms, expected, match_src)
self.check_expr_match(expr, discrim, arms, expected, match_src)
}
ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
ExprKind::Block(body, _) => self.check_block_with_expected(body, expected),
ExprKind::Call(callee, args) => self.check_call(expr, callee, args, expected),
ExprKind::Block(body, _) => self.check_expr_block(body, expected),
ExprKind::Call(callee, args) => self.check_expr_call(expr, callee, args, expected),
ExprKind::MethodCall(segment, receiver, args, _) => {
self.check_method_call(expr, segment, receiver, args, expected)
self.check_expr_method_call(expr, segment, receiver, args, expected)
}
ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),
ExprKind::Type(e, t) => {
@@ -528,7 +539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ascribed_ty
}
ExprKind::If(cond, then_expr, opt_else_expr) => {
self.check_then_else(cond, then_expr, opt_else_expr, expr.span, expected)
self.check_expr_if(cond, then_expr, opt_else_expr, expr.span, expected)
}
ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),
ExprKind::Array(args) => self.check_expr_array(args, expected, expr),
@@ -540,7 +551,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Struct(qpath, fields, ref base_expr) => {
self.check_expr_struct(expr, expected, qpath, fields, base_expr)
}
ExprKind::Field(base, field) => self.check_field(expr, base, field, expected),
ExprKind::Field(base, field) => self.check_expr_field(expr, base, field, expected),
ExprKind::Index(base, idx, brackets_span) => {
self.check_expr_index(base, idx, expr, brackets_span)
}
@@ -549,7 +560,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

fn check_expr_unary(
fn check_expr_unop(
&self,
unop: hir::UnOp,
oprnd: &'tcx hir::Expr<'tcx>,
@@ -699,8 +710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
qpath: &'tcx hir::QPath<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
args: Option<&'tcx [hir::Expr<'tcx>]>,
call: Option<&'tcx hir::Expr<'tcx>>,
call_expr_and_args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let (res, opt_ty, segs) =
@@ -730,7 +740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
segs,
opt_ty,
res,
call.map_or(expr.span, |e| e.span),
call_expr_and_args.map_or(expr.span, |(e, _)| e.span),
expr.span,
expr.hir_id,
)
@@ -769,7 +779,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We just want to check sizedness, so instead of introducing
// placeholder lifetimes with probing, we just replace higher lifetimes
// with fresh vars.
let span = args.and_then(|args| args.get(i)).map_or(expr.span, |arg| arg.span);
let span = call_expr_and_args
.and_then(|(_, args)| args.get(i))
.map_or(expr.span, |arg| arg.span);
let input = self.instantiate_binder_with_fresh_vars(
span,
infer::BoundRegionConversionTime::FnCall,
@@ -795,7 +807,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
self.require_type_is_sized_deferred(
output,
call.map_or(expr.span, |e| e.span),
call_expr_and_args.map_or(expr.span, |(e, _)| e.span),
ObligationCauseCode::SizedCallReturnType,
);
}
@@ -972,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.ret_coercion_span.get().is_none() {
self.ret_coercion_span.set(Some(e.span));
}
self.check_return_expr(e, true);
self.check_return_or_body_tail(e, true);
} else {
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
if self.ret_coercion_span.get().is_none() {
@@ -1035,7 +1047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
///
/// `explicit_return` is `true` if we're checking an explicit `return expr`,
/// and `false` if we're checking a trailing expression.
pub(super) fn check_return_expr(
pub(super) fn check_return_or_body_tail(
&self,
return_expr: &'tcx hir::Expr<'tcx>,
explicit_return: bool,
@@ -1259,7 +1271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// A generic function for checking the 'then' and 'else' clauses in an 'if'
// or 'if-else' expression.
fn check_then_else(
fn check_expr_if(
&self,
cond_expr: &'tcx hir::Expr<'tcx>,
then_expr: &'tcx hir::Expr<'tcx>,
@@ -1542,7 +1554,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

/// Checks a method call.
fn check_method_call(
fn check_expr_method_call(
&self,
expr: &'tcx hir::Expr<'tcx>,
segment: &'tcx hir::PathSegment<'tcx>,
@@ -2594,7 +2606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

// Check field access expressions
fn check_field(
fn check_expr_field(
&self,
expr: &'tcx hir::Expr<'tcx>,
base: &'tcx hir::Expr<'tcx>,
@@ -3535,8 +3547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let previous_diverges = self.diverges.get();

// The label blocks should have unit return value or diverge.
let ty =
self.check_block_with_expected(block, ExpectHasType(self.tcx.types.unit));
let ty = self.check_expr_block(block, ExpectHasType(self.tcx.types.unit));
if !ty.is_never() {
self.demand_suptype(block.span, self.tcx.types.unit, ty);
diverge = false;
@@ -3551,7 +3562,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if diverge { self.tcx.types.never } else { self.tcx.types.unit }
}

fn check_offset_of(
fn check_expr_offset_of(
&self,
container: &'tcx hir::Ty<'tcx>,
fields: &[Ident],
32 changes: 9 additions & 23 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
@@ -1306,30 +1306,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rustc_hir_analysis::hir_ty_lowering::RegionInferReason::Param(param),
)
.into(),
GenericParamDefKind::Type { has_default, .. } => {
if !infer_args && has_default {
// If we have a default, then it doesn't matter that we're not
// inferring the type arguments: we provide the default where any
// is missing.
tcx.type_of(param.def_id).instantiate(tcx, preceding_args).into()
} else {
// If no type arguments were provided, we have to infer them.
// This case also occurs as a result of some malformed input, e.g.
// a lifetime argument being given instead of a type parameter.
// Using inference instead of `Error` gives better error messages.
self.fcx.var_for_def(self.span, param)
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
if !infer_args && let Some(default) = param.default_value(tcx) {
// If we have a default, then it doesn't matter that we're not inferring
// the type/const arguments: We provide the default where any is missing.
return default.instantiate(tcx, preceding_args);
}
}
GenericParamDefKind::Const { has_default, .. } => {
if has_default {
if !infer_args {
return tcx
.const_param_default(param.def_id)
.instantiate(tcx, preceding_args)
.into();
}
}

// If no type/const arguments were provided, we have to infer them.
// This case also occurs as a result of some malformed input, e.g.,
// a lifetime argument being given instead of a type/const parameter.
// Using inference instead of `Error` gives better error messages.
self.fcx.var_for_def(self.span, param)
}
}
8 changes: 4 additions & 4 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
@@ -1565,7 +1565,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

// AST fragment checking
pub(in super::super) fn check_lit(
pub(in super::super) fn check_expr_lit(
&self,
lit: &hir::Lit,
expected: Expectation<'tcx>,
@@ -1747,7 +1747,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

if let Some(blk) = decl.origin.try_get_else() {
let previous_diverges = self.diverges.get();
let else_ty = self.check_block_with_expected(blk, NoExpectation);
let else_ty = self.check_expr_block(blk, NoExpectation);
let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
{
@@ -1805,7 +1805,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) {
let unit = self.tcx.types.unit;
let ty = self.check_block_with_expected(blk, ExpectHasType(unit));
let ty = self.check_expr_block(blk, ExpectHasType(unit));

// if the block produces a `!` value, that can always be
// (effectively) coerced to unit.
@@ -1814,7 +1814,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

pub(in super::super) fn check_block_with_expected(
pub(in super::super) fn check_expr_block(
&self,
blk: &'tcx hir::Block<'tcx>,
expected: Expectation<'tcx>,
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/op.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ use crate::Expectation;

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Checks a `a <op>= b`
pub(crate) fn check_binop_assign(
pub(crate) fn check_expr_binop_assign(
&self,
expr: &'tcx hir::Expr<'tcx>,
op: hir::BinOp,
@@ -85,7 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

/// Checks a potentially overloaded binary operator.
pub(crate) fn check_binop(
pub(crate) fn check_expr_binop(
&self,
expr: &'tcx hir::Expr<'tcx>,
op: hir::BinOp,
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
@@ -86,10 +86,10 @@ impl GenericParamDef {
tcx: TyCtxt<'tcx>,
) -> Option<EarlyBinder<'tcx, ty::GenericArg<'tcx>>> {
match self.kind {
GenericParamDefKind::Type { has_default, .. } if has_default => {
GenericParamDefKind::Type { has_default: true, .. } => {
Some(tcx.type_of(self.def_id).map_bound(|t| t.into()))
}
GenericParamDefKind::Const { has_default, .. } if has_default => {
GenericParamDefKind::Const { has_default: true, .. } => {
Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into()))
}
_ => None,
20 changes: 5 additions & 15 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -782,21 +782,11 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
fn generics(&mut self) -> &mut Self {
for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
match param.kind {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { has_default, .. } => {
if has_default {
self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
}
}
GenericParamDefKind::Const { has_default, .. } => {
self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
if has_default {
self.visit(
self.ev.tcx.const_param_default(param.def_id).instantiate_identity(),
);
}
}
if let GenericParamDefKind::Const { .. } = param.kind {
self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
}
if let Some(default) = param.default_value(self.ev.tcx) {
self.visit(default.instantiate_identity());
}
}
self
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
@@ -130,7 +130,7 @@ top_level_options!(
pub struct Options {
/// The crate config requested for the session, which may be combined
/// with additional crate configurations during the compile process.
#[rustc_lint_opt_deny_field_access("use `Session::crate_types` instead of this field")]
#[rustc_lint_opt_deny_field_access("use `TyCtxt::crate_types` instead of this field")]
crate_types: Vec<CrateType> [TRACKED],
optimize: OptLevel [TRACKED],
/// Include the `debug_assertions` flag in dependency tracking, since it
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1568,6 +1568,8 @@ symbols! {
readonly,
realloc,
reason,
receiver,
receiver_target,
recursion_limit,
reexport_test_harness_main,
ref_pat_eat_one_layer_2024,
88 changes: 86 additions & 2 deletions library/core/src/ops/deref.rs
Original file line number Diff line number Diff line change
@@ -294,14 +294,98 @@ unsafe impl<T: ?Sized> DerefPure for &T {}
#[unstable(feature = "deref_pure_trait", issue = "87121")]
unsafe impl<T: ?Sized> DerefPure for &mut T {}

/// Indicates that a struct can be used as a method receiver.
/// That is, a type can use this type as a type of `self`, like this:
/// ```compile_fail
/// # // This is currently compile_fail because the compiler-side parts
/// # // of arbitrary_self_types are not implemented
/// use std::ops::Receiver;
///
/// struct SmartPointer<T>(T);
///
/// impl<T> Receiver for SmartPointer<T> {
/// type Target = T;
/// }
///
/// struct MyContainedType;
///
/// impl MyContainedType {
/// fn method(self: SmartPointer<Self>) {
/// // ...
/// }
/// }
///
/// fn main() {
/// let ptr = SmartPointer(MyContainedType);
/// ptr.method();
/// }
/// ```
/// This trait is blanket implemented for any type which implements
/// [`Deref`], which includes stdlib pointer types like `Box<T>`,`Rc<T>`, `&T`,
/// and `Pin<P>`. For that reason, it's relatively rare to need to
/// implement this directly. You'll typically do this only if you need
/// to implement a smart pointer type which can't implement [`Deref`]; perhaps
/// because you're interfacing with another programming language and can't
/// guarantee that references comply with Rust's aliasing rules.
///
/// When looking for method candidates, Rust will explore a chain of possible
/// `Receiver`s, so for example each of the following methods work:
/// ```
/// use std::boxed::Box;
/// use std::rc::Rc;
///
/// // Both `Box` and `Rc` (indirectly) implement Receiver
///
/// struct MyContainedType;
///
/// fn main() {
/// let t = Rc::new(Box::new(MyContainedType));
/// t.method_a();
/// t.method_b();
/// t.method_c();
/// }
///
/// impl MyContainedType {
/// fn method_a(&self) {
///
/// }
/// fn method_b(self: &Box<Self>) {
///
/// }
/// fn method_c(self: &Rc<Box<Self>>) {
///
/// }
/// }
/// ```
#[lang = "receiver"]
#[cfg(not(bootstrap))]
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
pub trait Receiver {
/// The target type on which the method may be called.
#[cfg(not(bootstrap))]
#[rustc_diagnostic_item = "receiver_target"]
#[lang = "receiver_target"]
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
type Target: ?Sized;
}

#[cfg(not(bootstrap))]
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
impl<P: ?Sized, T: ?Sized> Receiver for P
where
P: Deref<Target = T>,
{
type Target = T;
}

/// Indicates that a struct can be used as a method receiver, without the
/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
/// `Rc<T>`, `&T`, and `Pin<P>`.
///
/// This trait will shortly be removed and replaced with a more generic
/// facility based around the current "arbitrary self types" unstable feature.
/// That new facility will use a replacement trait called `Receiver` which is
/// why this is now named `LegacyReceiver`.
/// That new facility will use the replacement trait above called `Receiver`
/// which is why this is now named `LegacyReceiver`.
#[cfg_attr(bootstrap, lang = "receiver")]
#[cfg_attr(not(bootstrap), lang = "legacy_receiver")]
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
3 changes: 3 additions & 0 deletions library/core/src/ops/mod.rs
Original file line number Diff line number Diff line change
@@ -170,6 +170,9 @@ pub use self::coroutine::{Coroutine, CoroutineState};
pub use self::deref::DerefPure;
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
pub use self::deref::LegacyReceiver;
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
#[cfg(not(bootstrap))]
pub use self::deref::Receiver;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::deref::{Deref, DerefMut};
#[stable(feature = "rust1", since = "1.0.0")]
449 changes: 449 additions & 0 deletions library/std/src/collections/hash/set.rs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/ui-fulldeps/internal-lints/bad_opt_access.rs
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ pub fn access_bad_option(sess: Session) {
//~^ ERROR use `Session::split_debuginfo` instead of this field

let _ = sess.opts.crate_types;
//~^ ERROR use `Session::crate_types` instead of this field
//~^ ERROR use `TyCtxt::crate_types` instead of this field

let _ = sess.opts.crate_name;
// okay!
2 changes: 1 addition & 1 deletion tests/ui-fulldeps/internal-lints/bad_opt_access.stderr
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ note: the lint level is defined here
LL | #![deny(rustc::bad_opt_access)]
| ^^^^^^^^^^^^^^^^^^^^^

error: use `Session::crate_types` instead of this field
error: use `TyCtxt::crate_types` instead of this field
--> $DIR/bad_opt_access.rs:17:13
|
LL | let _ = sess.opts.crate_types;
5 changes: 4 additions & 1 deletion triagebot.toml
Original file line number Diff line number Diff line change
@@ -212,6 +212,10 @@ trigger_files = [
"src/tools/rustdoc-gui",
"src/tools/rustdoc-js",
"src/tools/rustdoc-themes",

# Docs
"src/doc/rustdoc.md",
"src/doc/rustdoc/",
]
exclude_labels = [
"T-*",
@@ -971,7 +975,6 @@ cc = ["@kobzol"]
warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
"fmease",
"jieyouxu",
"jyn514",
"oli-obk",