Skip to content

Commit cb421c7

Browse files
committed
Auto merge of rust-lang#138525 - cuviper:beta-next, r=cuviper
[beta] backports - Windows: Fix error in `fs::rename` on Windows 1607 rust-lang#137528 - rustdoc: when merging target features, keep the highest stability rust-lang#137632 - doctests: fix merging on stable rust-lang#137899 - Revert wf sized check on beta rust-lang#138122 r? cuviper
2 parents b2af9a5 + ea14c4a commit cb421c7

File tree

73 files changed

+788
-721
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+788
-721
lines changed

compiler/rustc_codegen_ssa/src/target_features.rs

+44-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_middle::query::Providers;
1010
use rustc_middle::ty::TyCtxt;
1111
use rustc_session::parse::feature_err;
1212
use rustc_span::{Span, Symbol, sym};
13-
use rustc_target::target_features;
13+
use rustc_target::target_features::{self, Stability};
1414

1515
use crate::errors;
1616

@@ -87,12 +87,17 @@ pub(crate) fn from_target_feature_attr(
8787
// But ensure the ABI does not forbid enabling this.
8888
// Here we do assume that LLVM doesn't add even more implied features
8989
// we don't know about, at least no features that would have ABI effects!
90-
if abi_feature_constraints.incompatible.contains(&name.as_str()) {
91-
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
92-
span: item.span(),
93-
feature: name.as_str(),
94-
reason: "this feature is incompatible with the target ABI",
95-
});
90+
// We skip this logic in rustdoc, where we want to allow all target features of
91+
// all targets, so we can't check their ABI compatibility and anyway we are not
92+
// generating code so "it's fine".
93+
if !tcx.sess.opts.actually_rustdoc {
94+
if abi_feature_constraints.incompatible.contains(&name.as_str()) {
95+
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
96+
span: item.span(),
97+
feature: name.as_str(),
98+
reason: "this feature is incompatible with the target ABI",
99+
});
100+
}
96101
}
97102
target_features.push(TargetFeature { name, implied: name != feature_sym })
98103
}
@@ -142,11 +147,38 @@ pub(crate) fn provide(providers: &mut Providers) {
142147
rust_target_features: |tcx, cnum| {
143148
assert_eq!(cnum, LOCAL_CRATE);
144149
if tcx.sess.opts.actually_rustdoc {
145-
// rustdoc needs to be able to document functions that use all the features, so
146-
// whitelist them all
147-
rustc_target::target_features::all_rust_features()
148-
.map(|(a, b)| (a.to_string(), b))
149-
.collect()
150+
// HACK: rustdoc would like to pretend that we have all the target features, so we
151+
// have to merge all the lists into one. To ensure an unstable target never prevents
152+
// a stable one from working, we merge the stability info of all instances of the
153+
// same target feature name, with the "most stable" taking precedence. And then we
154+
// hope that this doesn't cause issues anywhere else in the compiler...
155+
let mut result: UnordMap<String, Stability> = Default::default();
156+
for (name, stability) in rustc_target::target_features::all_rust_features() {
157+
use std::collections::hash_map::Entry;
158+
match result.entry(name.to_owned()) {
159+
Entry::Vacant(vacant_entry) => {
160+
vacant_entry.insert(stability);
161+
}
162+
Entry::Occupied(mut occupied_entry) => {
163+
// Merge the two stabilities, "more stable" taking precedence.
164+
match (occupied_entry.get(), stability) {
165+
(Stability::Stable, _)
166+
| (
167+
Stability::Unstable { .. },
168+
Stability::Unstable { .. } | Stability::Forbidden { .. },
169+
)
170+
| (Stability::Forbidden { .. }, Stability::Forbidden { .. }) => {
171+
// The stability in the entry is at least as good as the new one, just keep it.
172+
}
173+
_ => {
174+
// Overwrite stabilite.
175+
occupied_entry.insert(stability);
176+
}
177+
}
178+
}
179+
}
180+
}
181+
result
150182
} else {
151183
tcx.sess
152184
.target

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+2-33
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,6 @@ fn check_associated_item(
11101110
let ty = tcx.type_of(item.def_id).instantiate_identity();
11111111
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
11121112
wfcx.register_wf_obligation(span, loc, ty.into());
1113-
check_sized_if_body(wfcx, item.def_id.expect_local(), ty, Some(span));
11141113
Ok(())
11151114
}
11161115
ty::AssocKind::Fn => {
@@ -1235,7 +1234,7 @@ fn check_type_defn<'tcx>(
12351234
),
12361235
wfcx.param_env,
12371236
ty,
1238-
tcx.require_lang_item(LangItem::Sized, Some(hir_ty.span)),
1237+
tcx.require_lang_item(LangItem::Sized, None),
12391238
);
12401239
}
12411240

@@ -1360,7 +1359,7 @@ fn check_item_type(
13601359
),
13611360
wfcx.param_env,
13621361
item_ty,
1363-
tcx.require_lang_item(LangItem::Sized, Some(ty_span)),
1362+
tcx.require_lang_item(LangItem::Sized, None),
13641363
);
13651364
}
13661365

@@ -1690,36 +1689,6 @@ fn check_fn_or_method<'tcx>(
16901689
);
16911690
}
16921691
}
1693-
1694-
// If the function has a body, additionally require that the return type is sized.
1695-
check_sized_if_body(
1696-
wfcx,
1697-
def_id,
1698-
sig.output(),
1699-
match hir_decl.output {
1700-
hir::FnRetTy::Return(ty) => Some(ty.span),
1701-
hir::FnRetTy::DefaultReturn(_) => None,
1702-
},
1703-
);
1704-
}
1705-
1706-
fn check_sized_if_body<'tcx>(
1707-
wfcx: &WfCheckingCtxt<'_, 'tcx>,
1708-
def_id: LocalDefId,
1709-
ty: Ty<'tcx>,
1710-
maybe_span: Option<Span>,
1711-
) {
1712-
let tcx = wfcx.tcx();
1713-
if let Some(body) = tcx.hir().maybe_body_owned_by(def_id) {
1714-
let span = maybe_span.unwrap_or(body.value.span);
1715-
1716-
wfcx.register_bound(
1717-
ObligationCause::new(span, def_id, traits::ObligationCauseCode::SizedReturnType),
1718-
wfcx.param_env,
1719-
ty,
1720-
tcx.require_lang_item(LangItem::Sized, Some(span)),
1721-
);
1722-
}
17231692
}
17241693

17251694
/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`.

compiler/rustc_hir_typeck/src/check.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,22 @@ pub(super) fn check_fn<'a, 'tcx>(
117117

118118
fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
119119

120-
// We checked the root's ret ty during wfcheck, but not the child.
121-
if fcx.tcx.is_typeck_child(fn_def_id.to_def_id()) {
122-
let return_or_body_span = match decl.output {
123-
hir::FnRetTy::DefaultReturn(_) => body.value.span,
124-
hir::FnRetTy::Return(ty) => ty.span,
125-
};
120+
let return_or_body_span = match decl.output {
121+
hir::FnRetTy::DefaultReturn(_) => body.value.span,
122+
hir::FnRetTy::Return(ty) => ty.span,
123+
};
126124

125+
fcx.require_type_is_sized(
126+
declared_ret_ty,
127+
return_or_body_span,
128+
ObligationCauseCode::SizedReturnType,
129+
);
130+
// We checked the root's signature during wfcheck, but not the child.
131+
if fcx.tcx.is_typeck_child(fn_def_id.to_def_id()) {
127132
fcx.require_type_is_sized(
128133
declared_ret_ty,
129134
return_or_body_span,
130-
ObligationCauseCode::SizedReturnType,
135+
ObligationCauseCode::WellFormed(None),
131136
);
132137
}
133138

compiler/rustc_hir_typeck/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ fn typeck_with_inspect<'tcx>(
186186
let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
187187
fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code);
188188

189+
fcx.require_type_is_sized(expected_type, body.value.span, ObligationCauseCode::ConstSized);
190+
189191
// Gather locals in statics (because of block expressions).
190192
GatherLocalsVisitor::new(&fcx).visit_body(body);
191193

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
707707
};
708708

709709
self.note_obligation_cause(&mut err, &obligation);
710+
self.point_at_returns_when_relevant(&mut err, &obligation);
710711
err.emit()
711712
}
712713
}
@@ -809,6 +810,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
809810
"Async",
810811
);
811812
self.note_obligation_cause(&mut err, &obligation);
813+
self.point_at_returns_when_relevant(&mut err, &obligation);
812814
return Some(err.emit());
813815
}
814816
}
@@ -854,6 +856,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
854856
"",
855857
);
856858
self.note_obligation_cause(&mut err, &obligation);
859+
self.point_at_returns_when_relevant(&mut err, &obligation);
857860
return Some(err.emit());
858861
}
859862

@@ -869,6 +872,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
869872
kind: expected_kind.as_str(),
870873
});
871874
self.note_obligation_cause(&mut err, &obligation);
875+
self.point_at_returns_when_relevant(&mut err, &obligation);
872876
return Some(err.emit());
873877
}
874878
}
@@ -2829,6 +2833,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
28292833
err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
28302834

28312835
self.note_obligation_cause(&mut err, &obligation);
2836+
self.point_at_returns_when_relevant(&mut err, &obligation);
28322837
self.dcx().try_steal_replace_and_emit_err(self.tcx.def_span(def_id), StashKey::Cycle, err)
28332838
}
28342839

compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs

+1
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
185185
suggest_increasing_limit,
186186
);
187187
self.note_obligation_cause(&mut err, &obligation);
188+
self.point_at_returns_when_relevant(&mut err, &obligation);
188189
err.emit()
189190
}
190191
}

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+56-9
Original file line numberDiff line numberDiff line change
@@ -1765,7 +1765,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17651765
};
17661766

17671767
err.code(E0746);
1768-
err.primary_message("return type cannot be a trait object without pointer indirection");
1768+
err.primary_message("return type cannot have an unboxed trait object");
17691769
err.children.clear();
17701770

17711771
let span = obligation.cause.span;
@@ -1781,13 +1781,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17811781
} else {
17821782
("dyn ", span.shrink_to_lo())
17831783
};
1784-
1785-
err.span_suggestion_verbose(
1786-
impl_span,
1787-
"consider returning an `impl Trait` instead of a `dyn Trait`",
1788-
"impl ",
1789-
Applicability::MaybeIncorrect,
1790-
);
1784+
let alternatively = if visitor
1785+
.returns
1786+
.iter()
1787+
.map(|expr| self.typeck_results.as_ref().unwrap().expr_ty_adjusted_opt(expr))
1788+
.collect::<FxHashSet<_>>()
1789+
.len()
1790+
<= 1
1791+
{
1792+
err.span_suggestion_verbose(
1793+
impl_span,
1794+
"consider returning an `impl Trait` instead of a `dyn Trait`",
1795+
"impl ",
1796+
Applicability::MaybeIncorrect,
1797+
);
1798+
"alternatively, "
1799+
} else {
1800+
err.help("if there were a single returned type, you could use `impl Trait` instead");
1801+
""
1802+
};
17911803

17921804
let mut sugg = vec![
17931805
(span.shrink_to_lo(), format!("Box<{pre}")),
@@ -1819,7 +1831,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18191831

18201832
err.multipart_suggestion(
18211833
format!(
1822-
"alternatively, box the return type, and wrap all of the returned values in \
1834+
"{alternatively}box the return type, and wrap all of the returned values in \
18231835
`Box::new`",
18241836
),
18251837
sugg,
@@ -1829,6 +1841,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18291841
true
18301842
}
18311843

1844+
pub(super) fn point_at_returns_when_relevant(
1845+
&self,
1846+
err: &mut Diag<'_>,
1847+
obligation: &PredicateObligation<'tcx>,
1848+
) {
1849+
match obligation.cause.code().peel_derives() {
1850+
ObligationCauseCode::SizedReturnType => {}
1851+
_ => return,
1852+
}
1853+
1854+
let hir = self.tcx.hir();
1855+
let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
1856+
if let hir::Node::Item(hir::Item {
1857+
kind: hir::ItemKind::Fn { body: body_id, .. }, ..
1858+
}) = node
1859+
{
1860+
let body = hir.body(*body_id);
1861+
// Point at all the `return`s in the function as they have failed trait bounds.
1862+
let mut visitor = ReturnsVisitor::default();
1863+
visitor.visit_body(body);
1864+
let typeck_results = self.typeck_results.as_ref().unwrap();
1865+
for expr in &visitor.returns {
1866+
if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) {
1867+
let ty = self.resolve_vars_if_possible(returned_ty);
1868+
if ty.references_error() {
1869+
// don't print out the [type error] here
1870+
err.downgrade_to_delayed_bug();
1871+
} else {
1872+
err.span_label(expr.span, format!("this returned value is of type `{ty}`"));
1873+
}
1874+
}
1875+
}
1876+
}
1877+
}
1878+
18321879
pub(super) fn report_closure_arg_mismatch(
18331880
&self,
18341881
span: Span,

library/std/src/fs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2425,7 +2425,7 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
24252425
/// # Platform-specific behavior
24262426
///
24272427
/// This function currently corresponds to the `rename` function on Unix
2428-
/// and the `SetFileInformationByHandle` function on Windows.
2428+
/// and the `MoveFileExW` or `SetFileInformationByHandle` function on Windows.
24292429
///
24302430
/// Because of this, the behavior when both `from` and `to` exist differs. On
24312431
/// Unix, if `from` is a directory, `to` must also be an (empty) directory. If

0 commit comments

Comments
 (0)