Skip to content

Commit 397641f

Browse files
committed
Auto merge of #112465 - GuillaumeGomez:rollup-gyh5buc, r=GuillaumeGomez
Rollup of 3 pull requests Successful merges: - #112260 (Improve document of `unsafe_code` lint) - #112429 ([rustdoc] List matching impls on type aliases) - #112442 (Deduplicate identical region constraints in new solver) r? `@ghost` `@rustbot` modify labels: rollup
2 parents d7ad9d9 + 4ef7257 commit 397641f

File tree

7 files changed

+232
-42
lines changed

7 files changed

+232
-42
lines changed

Diff for: compiler/rustc_lint/src/builtin.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,9 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
286286
}
287287

288288
declare_lint! {
289-
/// The `unsafe_code` lint catches usage of `unsafe` code.
289+
/// The `unsafe_code` lint catches usage of `unsafe` code and other
290+
/// potentially unsound constructs like `no_mangle`, `export_name`,
291+
/// and `link_section`.
290292
///
291293
/// ### Example
292294
///
@@ -297,17 +299,29 @@ declare_lint! {
297299
///
298300
/// }
299301
/// }
302+
///
303+
/// #[no_mangle]
304+
/// fn func_0() { }
305+
///
306+
/// #[export_name = "exported_symbol_name"]
307+
/// pub fn name_in_rust() { }
308+
///
309+
/// #[no_mangle]
310+
/// #[link_section = ".example_section"]
311+
/// pub static VAR1: u32 = 1;
300312
/// ```
301313
///
302314
/// {{produces}}
303315
///
304316
/// ### Explanation
305317
///
306-
/// This lint is intended to restrict the usage of `unsafe`, which can be
307-
/// difficult to use correctly.
318+
/// This lint is intended to restrict the usage of `unsafe` blocks and other
319+
/// constructs (including, but not limited to `no_mangle`, `link_section`
320+
/// and `export_name` attributes) wrong usage of which causes undefined
321+
/// behavior.
308322
UNSAFE_CODE,
309323
Allow,
310-
"usage of `unsafe` code"
324+
"usage of `unsafe` code and other potentially unsound constructs"
311325
}
312326

313327
declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);

Diff for: compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
1212
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
1313
use crate::solve::{CanonicalResponse, QueryResult, Response};
14+
use rustc_data_structures::fx::FxHashSet;
1415
use rustc_index::IndexVec;
1516
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
1617
use rustc_infer::infer::canonical::CanonicalVarValues;
@@ -147,7 +148,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
147148
// Cannot use `take_registered_region_obligations` as we may compute the response
148149
// inside of a `probe` whenever we have multiple choices inside of the solver.
149150
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
150-
let region_constraints = self.infcx.with_region_constraints(|region_constraints| {
151+
let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| {
151152
make_query_region_constraints(
152153
self.tcx(),
153154
region_obligations
@@ -157,6 +158,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
157158
)
158159
});
159160

161+
let mut seen = FxHashSet::default();
162+
region_constraints.outlives.retain(|outlives| seen.insert(*outlives));
163+
160164
let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
161165
// Only return opaque type keys for newly-defined opaques
162166
opaque_types.retain(|(a, _)| {

Diff for: library/core/src/ptr/mut_ptr.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ impl<T: ?Sized> *mut T {
106106
/// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit
107107
/// coercion.
108108
///
109-
/// [`cast_mut`]: #method.cast_mut
109+
/// [`cast_mut`]: pointer::cast_mut
110110
#[stable(feature = "ptr_const_cast", since = "1.65.0")]
111111
#[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
112112
#[inline(always)]
@@ -117,7 +117,7 @@ impl<T: ?Sized> *mut T {
117117
/// Casts a pointer to its raw bits.
118118
///
119119
/// This is equivalent to `as usize`, but is more specific to enhance readability.
120-
/// The inverse method is [`from_bits`](#method.from_bits-1).
120+
/// The inverse method is [`from_bits`](pointer#method.from_bits-1).
121121
///
122122
/// In particular, `*p as usize` and `p as usize` will both compile for
123123
/// pointers to numeric types but do very different things, so using this
@@ -153,7 +153,7 @@ impl<T: ?Sized> *mut T {
153153
/// Creates a pointer from its raw bits.
154154
///
155155
/// This is equivalent to `as *mut T`, but is more specific to enhance readability.
156-
/// The inverse method is [`to_bits`](#method.to_bits-1).
156+
/// The inverse method is [`to_bits`](pointer#method.to_bits-1).
157157
///
158158
/// # Examples
159159
///
@@ -303,7 +303,7 @@ impl<T: ?Sized> *mut T {
303303
///
304304
/// For the mutable counterpart see [`as_mut`].
305305
///
306-
/// [`as_uninit_ref`]: #method.as_uninit_ref-1
306+
/// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1
307307
/// [`as_mut`]: #method.as_mut
308308
///
309309
/// # Safety
@@ -369,7 +369,7 @@ impl<T: ?Sized> *mut T {
369369
///
370370
/// For the mutable counterpart see [`as_uninit_mut`].
371371
///
372-
/// [`as_ref`]: #method.as_ref-1
372+
/// [`as_ref`]: pointer#method.as_ref-1
373373
/// [`as_uninit_mut`]: #method.as_uninit_mut
374374
///
375375
/// # Safety
@@ -624,7 +624,7 @@ impl<T: ?Sized> *mut T {
624624
/// For the shared counterpart see [`as_ref`].
625625
///
626626
/// [`as_uninit_mut`]: #method.as_uninit_mut
627-
/// [`as_ref`]: #method.as_ref-1
627+
/// [`as_ref`]: pointer#method.as_ref-1
628628
///
629629
/// # Safety
630630
///
@@ -689,7 +689,7 @@ impl<T: ?Sized> *mut T {
689689
/// For the shared counterpart see [`as_uninit_ref`].
690690
///
691691
/// [`as_mut`]: #method.as_mut
692-
/// [`as_uninit_ref`]: #method.as_uninit_ref-1
692+
/// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1
693693
///
694694
/// # Safety
695695
///
@@ -779,7 +779,7 @@ impl<T: ?Sized> *mut T {
779779
///
780780
/// This function is the inverse of [`offset`].
781781
///
782-
/// [`offset`]: #method.offset-1
782+
/// [`offset`]: pointer#method.offset-1
783783
///
784784
/// # Safety
785785
///
@@ -2051,7 +2051,7 @@ impl<T> *mut [T] {
20512051
///
20522052
/// For the mutable counterpart see [`as_uninit_slice_mut`].
20532053
///
2054-
/// [`as_ref`]: #method.as_ref-1
2054+
/// [`as_ref`]: pointer#method.as_ref-1
20552055
/// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut
20562056
///
20572057
/// # Safety

Diff for: src/librustdoc/html/render/mod.rs

+78-12
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@ use rustc_data_structures::captures::Captures;
5353
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5454
use rustc_hir::def_id::{DefId, DefIdSet};
5555
use rustc_hir::Mutability;
56+
use rustc_infer::infer::TyCtxtInferExt;
57+
use rustc_infer::traits::{Obligation, ObligationCause};
5658
use rustc_middle::middle::stability;
57-
use rustc_middle::ty::TyCtxt;
59+
use rustc_middle::ty::{ParamEnv, TyCtxt};
5860
use rustc_span::{
5961
symbol::{sym, Symbol},
6062
BytePos, FileName, RealFileName,
6163
};
64+
use rustc_trait_selection::traits::ObligationCtxt;
6265
use serde::ser::{SerializeMap, SerializeSeq};
6366
use serde::{Serialize, Serializer};
6467

@@ -1112,28 +1115,76 @@ fn render_assoc_items<'a, 'cx: 'a>(
11121115
containing_item: &'a clean::Item,
11131116
it: DefId,
11141117
what: AssocItemRender<'a>,
1118+
aliased_type: Option<DefId>,
11151119
) -> impl fmt::Display + 'a + Captures<'cx> {
11161120
let mut derefs = DefIdSet::default();
11171121
derefs.insert(it);
11181122
display_fn(move |f| {
1119-
render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs);
1123+
render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs, aliased_type);
11201124
Ok(())
11211125
})
11221126
}
11231127

1128+
/// Check whether `impl_def_id` may apply to *some instantiation* of `item_def_id`.
1129+
fn is_valid_impl_for(tcx: TyCtxt<'_>, item_def_id: DefId, impl_def_id: DefId) -> bool {
1130+
let infcx = tcx.infer_ctxt().intercrate(true).build();
1131+
let ocx = ObligationCtxt::new(&infcx);
1132+
let param_env = ParamEnv::empty();
1133+
1134+
let alias_substs = infcx.fresh_substs_for_item(rustc_span::DUMMY_SP, item_def_id);
1135+
let alias_ty = tcx.type_of(item_def_id).subst(tcx, alias_substs);
1136+
let alias_bounds = tcx.predicates_of(item_def_id).instantiate(tcx, alias_substs);
1137+
1138+
let impl_substs = infcx.fresh_substs_for_item(rustc_span::DUMMY_SP, impl_def_id);
1139+
let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, impl_substs);
1140+
let impl_bounds = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
1141+
1142+
if ocx.eq(&ObligationCause::dummy(), param_env, impl_self_ty, alias_ty).is_err() {
1143+
return false;
1144+
}
1145+
ocx.register_obligations(
1146+
alias_bounds
1147+
.iter()
1148+
.chain(impl_bounds)
1149+
.map(|(p, _)| Obligation::new(tcx, ObligationCause::dummy(), param_env, p)),
1150+
);
1151+
1152+
let errors = ocx.select_where_possible();
1153+
errors.is_empty()
1154+
}
1155+
1156+
// If `aliased_type` is `Some`, it means `it` is a type alias and `aliased_type` is the "actual"
1157+
// type aliased behind `it`. It is used to check whether or not the implementation of the aliased
1158+
// type can be displayed on the alias doc page.
11241159
fn render_assoc_items_inner(
11251160
mut w: &mut dyn fmt::Write,
11261161
cx: &mut Context<'_>,
11271162
containing_item: &clean::Item,
11281163
it: DefId,
11291164
what: AssocItemRender<'_>,
11301165
derefs: &mut DefIdSet,
1166+
aliased_type: Option<DefId>,
11311167
) {
11321168
info!("Documenting associated items of {:?}", containing_item.name);
11331169
let shared = Rc::clone(&cx.shared);
11341170
let cache = &shared.cache;
1135-
let Some(v) = cache.impls.get(&it) else { return };
1136-
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
1171+
let empty = Vec::new();
1172+
let v = match cache.impls.get(&it) {
1173+
Some(v) => v,
1174+
None => &empty,
1175+
};
1176+
let v2 = match aliased_type {
1177+
Some(aliased_type) => cache.impls.get(&aliased_type).unwrap_or(&empty),
1178+
None => &empty,
1179+
};
1180+
if v.is_empty() && v2.is_empty() {
1181+
return;
1182+
}
1183+
let mut saw_impls = FxHashSet::default();
1184+
let (non_trait, traits): (Vec<_>, _) =
1185+
v.iter().chain(v2).partition(|i| i.inner_impl().trait_.is_none());
1186+
let tcx = cx.tcx();
1187+
let is_alias = aliased_type.is_some();
11371188
if !non_trait.is_empty() {
11381189
let mut tmp_buf = Buffer::html();
11391190
let (render_mode, id, class_html) = match what {
@@ -1165,6 +1216,12 @@ fn render_assoc_items_inner(
11651216
};
11661217
let mut impls_buf = Buffer::html();
11671218
for i in &non_trait {
1219+
if !saw_impls.insert(i.def_id()) {
1220+
continue;
1221+
}
1222+
if is_alias && !is_valid_impl_for(tcx, it, i.def_id()) {
1223+
continue;
1224+
}
11681225
render_impl(
11691226
&mut impls_buf,
11701227
cx,
@@ -1193,9 +1250,14 @@ fn render_assoc_items_inner(
11931250
if !traits.is_empty() {
11941251
let deref_impl =
11951252
traits.iter().find(|t| t.trait_did() == cx.tcx().lang_items().deref_trait());
1196-
if let Some(impl_) = deref_impl {
1253+
if let Some(impl_) = deref_impl &&
1254+
(!is_alias || is_valid_impl_for(tcx, it, impl_.def_id()))
1255+
{
11971256
let has_deref_mut =
1198-
traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait());
1257+
traits.iter().any(|t| {
1258+
t.trait_did() == cx.tcx().lang_items().deref_mut_trait() &&
1259+
(!is_alias || is_valid_impl_for(tcx, it, t.def_id()))
1260+
});
11991261
render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs);
12001262
}
12011263

@@ -1205,10 +1267,14 @@ fn render_assoc_items_inner(
12051267
return;
12061268
}
12071269

1208-
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
1209-
traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
1210-
let (blanket_impl, concrete): (Vec<&Impl>, _) =
1211-
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
1270+
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = traits
1271+
.into_iter()
1272+
.filter(|t| saw_impls.insert(t.def_id()))
1273+
.partition(|t| t.inner_impl().kind.is_auto());
1274+
let (blanket_impl, concrete): (Vec<&Impl>, _) = concrete
1275+
.into_iter()
1276+
.filter(|t| !is_alias || is_valid_impl_for(tcx, it, t.def_id()))
1277+
.partition(|t| t.inner_impl().kind.is_blanket());
12121278

12131279
render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl);
12141280
}
@@ -1247,10 +1313,10 @@ fn render_deref_methods(
12471313
return;
12481314
}
12491315
}
1250-
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
1316+
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs, None);
12511317
} else if let Some(prim) = target.primitive_type() {
12521318
if let Some(&did) = cache.primitive_locations.get(&prim) {
1253-
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
1319+
render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs, None);
12541320
}
12551321
}
12561322
}

0 commit comments

Comments
 (0)