authorbors <bors@rust-lang.org> 2026-02-09 19:19:04 UTC
committerbors <bors@rust-lang.org> 2026-02-09 19:19:04 UTC
log18d13b5332916ffca8eadb9106d54b5b434e9978
tree78748a881429728991bfd3b6b8312c91ec9d8cb8
parent71dc761bfe791895c5997dda654dca1dad817413
parent2f16df1832cf21abfcd4f315a75c0b0bb26127ac

Auto merge of #152399 - matthiaskrgr:rollup-uDIDnAN, r=matthiaskrgr

Rollup of 12 pull requests Successful merges: - rust-lang/rust#152388 (`rust-analyzer` subtree update) - rust-lang/rust#151613 (Align `ArrayWindows` trait impls with `Windows`) - rust-lang/rust#152134 (Set crt_static_allow_dylibs to true for Emscripten target) - rust-lang/rust#152166 (cleanup some more things in `proc_macro::bridge`) - rust-lang/rust#152236 (compiletest: `-Zunstable-options` for json targets) - rust-lang/rust#152287 (Fix an ICE in the vtable iteration for a trait reference in const eval when a supertrait not implemented) - rust-lang/rust#142957 (std: introduce path normalize methods at top of `std::path`) - rust-lang/rust#145504 (Add some conversion trait impls) - rust-lang/rust#152131 (Port rustc_no_implicit_bounds attribute to parser.) - rust-lang/rust#152315 (fix: rhs_span to rhs_span_new) - rust-lang/rust#152327 (Check stalled coroutine obligations eagerly) - rust-lang/rust#152377 (Rename the query system's `JobOwner` to `ActiveJobGuard`, and include `key_hash`)

119 files changed, 1906 insertions(+), 979 deletions(-)

compiler/rustc_attr_parsing/src/attributes/crate_level.rs+9
......@@ -283,3 +283,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcPreserveUbChecksParser {
283283 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
284284 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks;
285285}
286
287pub(crate) struct RustcNoImplicitBoundsParser;
288
289impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitBoundsParser {
290 const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds];
291 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
292 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
293 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds;
294}
compiler/rustc_attr_parsing/src/context.rs+1
......@@ -282,6 +282,7 @@ attribute_parsers!(
282282 Single<WithoutArgs<RustcMainParser>>,
283283 Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
284284 Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
285 Single<WithoutArgs<RustcNoImplicitBoundsParser>>,
285286 Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
286287 Single<WithoutArgs<RustcNounwindParser>>,
287288 Single<WithoutArgs<RustcOffloadKernelParser>>,
compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs+1-1
......@@ -1695,7 +1695,7 @@ fn suggest_ampmut<'tcx>(
16951695 && let Either::Left(rhs_stmt_new) = body.stmt_at(*assign)
16961696 && let StatementKind::Assign(box (_, rvalue_new)) = &rhs_stmt_new.kind
16971697 && let rhs_span_new = rhs_stmt_new.source_info.span
1698 && let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span)
1698 && let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span_new)
16991699 {
17001700 (rvalue, rhs_span, rhs_str) = (rvalue_new, rhs_span_new, rhs_str_new);
17011701 }
compiler/rustc_borrowck/src/lib.rs+5
......@@ -121,6 +121,11 @@ fn mir_borrowck(
121121 let (input_body, _) = tcx.mir_promoted(def);
122122 debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
123123
124 // We should eagerly check stalled coroutine obligations from HIR typeck.
125 // Not doing so leads to silent normalization failures later, which will
126 // fail to register opaque types in the next solver.
127 tcx.check_coroutine_obligations(def)?;
128
124129 let input_body: &Body<'_> = &input_body.borrow();
125130 if let Some(guar) = input_body.tainted_by_errors {
126131 debug!("Skipping borrowck because of tainted body");
compiler/rustc_hir/src/attrs/data_structures.rs+3
......@@ -1177,6 +1177,9 @@ pub enum AttributeKind {
11771177 /// Represents `#[rustc_no_implicit_autorefs]`
11781178 RustcNoImplicitAutorefs,
11791179
1180 /// Represents `#[rustc_no_implicit_bounds]`
1181 RustcNoImplicitBounds,
1182
11801183 /// Represents `#[rustc_non_const_trait_method]`.
11811184 RustcNonConstTraitMethod,
11821185
compiler/rustc_hir/src/attrs/encode_cross_crate.rs+1
......@@ -137,6 +137,7 @@ impl AttributeKind {
137137 RustcMustImplementOneOf { .. } => No,
138138 RustcNeverReturnsNullPointer => Yes,
139139 RustcNoImplicitAutorefs => Yes,
140 RustcNoImplicitBounds => No,
140141 RustcNonConstTraitMethod => No, // should be reported via other queries like `constness`
141142 RustcNounwind => No,
142143 RustcObjcClass { .. } => No,
compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs+6-4
......@@ -4,15 +4,16 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
44use rustc_errors::codes::*;
55use rustc_errors::struct_span_code_err;
66use rustc_hir as hir;
7use rustc_hir::PolyTraitRef;
7use rustc_hir::attrs::AttributeKind;
88use rustc_hir::def::{DefKind, Res};
99use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
10use rustc_hir::{PolyTraitRef, find_attr};
1011use rustc_middle::bug;
1112use rustc_middle::ty::{
1213 self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
1314 TypeVisitor, Upcast,
1415};
15use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
16use rustc_span::{ErrorGuaranteed, Ident, Span, kw};
1617use rustc_trait_selection::traits;
1718use smallvec::SmallVec;
1819use tracing::{debug, instrument};
......@@ -170,7 +171,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
170171 let tcx = self.tcx();
171172
172173 // Skip adding any default bounds if `#![rustc_no_implicit_bounds]`
173 if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) {
174 if find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) {
174175 return;
175176 }
176177
......@@ -284,7 +285,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
284285 context: ImpliedBoundsContext<'tcx>,
285286 ) -> bool {
286287 let collected = collect_bounds(hir_bounds, context, trait_def_id);
287 !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
288 !find_attr!(self.tcx().get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds)
289 && !collected.any()
288290 }
289291
290292 fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) {
compiler/rustc_interface/src/passes.rs+7-11
......@@ -1116,18 +1116,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
11161116 {
11171117 tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id);
11181118 }
1119 if tcx.is_coroutine(def_id.to_def_id()) {
1120 tcx.ensure_ok().mir_coroutine_witnesses(def_id);
1121 let _ = tcx.ensure_ok().check_coroutine_obligations(
1122 tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
1119 if tcx.is_coroutine(def_id.to_def_id())
1120 && (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()))
1121 {
1122 // Eagerly check the unsubstituted layout for cycles.
1123 tcx.ensure_ok().layout_of(
1124 ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
1125 .as_query_input(tcx.type_of(def_id).instantiate_identity()),
11231126 );
1124 if !tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()) {
1125 // Eagerly check the unsubstituted layout for cycles.
1126 tcx.ensure_ok().layout_of(
1127 ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
1128 .as_query_input(tcx.type_of(def_id).instantiate_identity()),
1129 );
1130 }
11311127 }
11321128 });
11331129 });
compiler/rustc_middle/src/ty/context/tls.rs+1-2
......@@ -16,8 +16,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
1616 /// The current `TyCtxt`.
1717 pub tcx: TyCtxt<'tcx>,
1818
19 /// The current query job, if any. This is updated by `JobOwner::start` in
20 /// `ty::query::plumbing` when executing a query.
19 /// The current query job, if any.
2120 pub query: Option<QueryJobId>,
2221
2322 /// Used to prevent queries from calling too deeply.
compiler/rustc_passes/src/check_attr.rs+1-1
......@@ -330,6 +330,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
330330 | AttributeKind::RustcMir(_)
331331 | AttributeKind::RustcNeverReturnsNullPointer
332332 | AttributeKind::RustcNoImplicitAutorefs
333 | AttributeKind::RustcNoImplicitBounds
333334 | AttributeKind::RustcNonConstTraitMethod
334335 | AttributeKind::RustcNounwind
335336 | AttributeKind::RustcObjcClass { .. }
......@@ -413,7 +414,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
413414 // crate-level attrs, are checked below
414415 | sym::feature
415416 | sym::register_tool
416 | sym::rustc_no_implicit_bounds
417417 | sym::test_runner,
418418 ..
419419 ] => {}
compiler/rustc_query_impl/src/execution.rs+23-17
......@@ -83,14 +83,18 @@ pub(crate) fn gather_active_jobs_inner<'tcx, K: Copy>(
8383 Some(())
8484}
8585
86/// A type representing the responsibility to execute the job in the `job` field.
87/// This will poison the relevant query if dropped.
88struct JobOwner<'tcx, K>
86/// Guard object representing the responsibility to execute a query job and
87/// mark it as completed.
88///
89/// This will poison the relevant query key if it is dropped without calling
90/// [`Self::complete`].
91struct ActiveJobGuard<'tcx, K>
8992where
9093 K: Eq + Hash + Copy,
9194{
9295 state: &'tcx QueryState<'tcx, K>,
9396 key: K,
97 key_hash: u64,
9498}
9599
96100#[cold]
......@@ -137,20 +141,19 @@ fn handle_cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
137141 }
138142}
139143
140impl<'tcx, K> JobOwner<'tcx, K>
144impl<'tcx, K> ActiveJobGuard<'tcx, K>
141145where
142146 K: Eq + Hash + Copy,
143147{
144148 /// Completes the query by updating the query cache with the `result`,
145 /// signals the waiter and forgets the JobOwner, so it won't poison the query
146 fn complete<C>(self, cache: &C, key_hash: u64, result: C::Value, dep_node_index: DepNodeIndex)
149 /// signals the waiter, and forgets the guard so it won't poison the query.
150 fn complete<C>(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex)
147151 where
148152 C: QueryCache<Key = K>,
149153 {
150 let key = self.key;
151 let state = self.state;
152
153 // Forget ourself so our destructor won't poison the query
154 // Forget ourself so our destructor won't poison the query.
155 // (Extract fields by value first to make sure we don't leak anything.)
156 let Self { state, key, key_hash }: Self = self;
154157 mem::forget(self);
155158
156159 // Mark as complete before we remove the job from the active state
......@@ -174,7 +177,7 @@ where
174177 }
175178}
176179
177impl<'tcx, K> Drop for JobOwner<'tcx, K>
180impl<'tcx, K> Drop for ActiveJobGuard<'tcx, K>
178181where
179182 K: Eq + Hash + Copy,
180183{
......@@ -182,11 +185,10 @@ where
182185 #[cold]
183186 fn drop(&mut self) {
184187 // Poison the query so jobs waiting on it panic.
185 let state = self.state;
188 let Self { state, key, key_hash } = *self;
186189 let job = {
187 let key_hash = sharded::make_hash(&self.key);
188190 let mut shard = state.active.lock_shard_by_hash(key_hash);
189 match shard.find_entry(key_hash, equivalent_key(&self.key)) {
191 match shard.find_entry(key_hash, equivalent_key(&key)) {
190192 Err(_) => panic!(),
191193 Ok(occupied) => {
192194 let ((key, value), vacant) = occupied.remove();
......@@ -342,11 +344,13 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>(
342344 id: QueryJobId,
343345 dep_node: Option<DepNode>,
344346) -> (C::Value, Option<DepNodeIndex>) {
345 // Use `JobOwner` so the query will be poisoned if executing it panics.
346 let job_owner = JobOwner { state, key };
347 // Set up a guard object that will automatically poison the query if a
348 // panic occurs while executing the query (or any intermediate plumbing).
349 let job_guard = ActiveJobGuard { state, key, key_hash };
347350
348351 debug_assert_eq!(qcx.tcx.dep_graph.is_fully_enabled(), INCR);
349352
353 // Delegate to another function to actually execute the query job.
350354 let (result, dep_node_index) = if INCR {
351355 execute_job_incr(query, qcx, qcx.tcx.dep_graph.data().unwrap(), key, dep_node, id)
352356 } else {
......@@ -388,7 +392,9 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>(
388392 }
389393 }
390394 }
391 job_owner.complete(cache, key_hash, result, dep_node_index);
395
396 // Tell the guard to perform completion bookkeeping, and also to not poison the query.
397 job_guard.complete(cache, result, dep_node_index);
392398
393399 (result, Some(dep_node_index))
394400}
compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs+7
......@@ -19,8 +19,15 @@ pub(crate) fn target() -> Target {
1919 pre_link_args,
2020 post_link_args,
2121 relocation_model: RelocModel::Pic,
22 // crt_static should always be true for an executable and always false
23 // for a shared library. There is no easy way to indicate this and it
24 // doesn't seem to matter much so we set crt_static_allows_dylibs to
25 // true and leave crt_static as true when linking dynamic libraries.
26 // wasi also sets crt_static_allows_dylibs: true so this is at least
27 // aligned between wasm targets.
2228 crt_static_respected: true,
2329 crt_static_default: true,
30 crt_static_allows_dylibs: true,
2431 panic_strategy: PanicStrategy::Unwind,
2532 no_default_libraries: false,
2633 families: cvs!["unix", "wasm"],
compiler/rustc_trait_selection/src/traits/vtable.rs+2-6
......@@ -12,7 +12,7 @@ use rustc_span::DUMMY_SP;
1212use smallvec::{SmallVec, smallvec};
1313use tracing::debug;
1414
15use crate::traits::{impossible_predicates, is_vtable_safe_method};
15use crate::traits::is_vtable_safe_method;
1616
1717#[derive(Clone, Debug)]
1818pub enum VtblSegment<'tcx> {
......@@ -271,11 +271,7 @@ fn vtable_entries<'tcx>(
271271 // do not hold for this particular set of type parameters.
272272 // Note that this method could then never be called, so we
273273 // do not want to try and codegen it, in that case (see #23435).
274 let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args);
275 if impossible_predicates(
276 tcx,
277 predicates.map(|(predicate, _)| predicate).collect(),
278 ) {
274 if tcx.instantiate_and_check_impossible_predicates((def_id, args)) {
279275 debug!("vtable_entries: predicates do not hold");
280276 return VtblEntry::Vacant;
281277 }
library/core/src/cell.rs+24
......@@ -689,6 +689,30 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
689689#[unstable(feature = "dispatch_from_dyn", issue = "none")]
690690impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Cell<U>> for Cell<T> {}
691691
692#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
693impl<T, const N: usize> AsRef<[Cell<T>; N]> for Cell<[T; N]> {
694 #[inline]
695 fn as_ref(&self) -> &[Cell<T>; N] {
696 self.as_array_of_cells()
697 }
698}
699
700#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
701impl<T, const N: usize> AsRef<[Cell<T>]> for Cell<[T; N]> {
702 #[inline]
703 fn as_ref(&self) -> &[Cell<T>] {
704 &*self.as_array_of_cells()
705 }
706}
707
708#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
709impl<T> AsRef<[Cell<T>]> for Cell<[T]> {
710 #[inline]
711 fn as_ref(&self) -> &[Cell<T>] {
712 self.as_slice_of_cells()
713 }
714}
715
692716impl<T> Cell<[T]> {
693717 /// Returns a `&[Cell<T>]` from a `&Cell<[T]>`
694718 ///
library/core/src/mem/maybe_uninit.rs+50
......@@ -1532,6 +1532,56 @@ impl<T, const N: usize> MaybeUninit<[T; N]> {
15321532 }
15331533}
15341534
1535#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
1536impl<T, const N: usize> From<[MaybeUninit<T>; N]> for MaybeUninit<[T; N]> {
1537 #[inline]
1538 fn from(arr: [MaybeUninit<T>; N]) -> Self {
1539 arr.transpose()
1540 }
1541}
1542
1543#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
1544impl<T, const N: usize> AsRef<[MaybeUninit<T>; N]> for MaybeUninit<[T; N]> {
1545 #[inline]
1546 fn as_ref(&self) -> &[MaybeUninit<T>; N] {
1547 // SAFETY: T and MaybeUninit<T> have the same layout
1548 unsafe { &*ptr::from_ref(self).cast() }
1549 }
1550}
1551
1552#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
1553impl<T, const N: usize> AsRef<[MaybeUninit<T>]> for MaybeUninit<[T; N]> {
1554 #[inline]
1555 fn as_ref(&self) -> &[MaybeUninit<T>] {
1556 &*AsRef::<[MaybeUninit<T>; N]>::as_ref(self)
1557 }
1558}
1559
1560#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
1561impl<T, const N: usize> AsMut<[MaybeUninit<T>; N]> for MaybeUninit<[T; N]> {
1562 #[inline]
1563 fn as_mut(&mut self) -> &mut [MaybeUninit<T>; N] {
1564 // SAFETY: T and MaybeUninit<T> have the same layout
1565 unsafe { &mut *ptr::from_mut(self).cast() }
1566 }
1567}
1568
1569#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
1570impl<T, const N: usize> AsMut<[MaybeUninit<T>]> for MaybeUninit<[T; N]> {
1571 #[inline]
1572 fn as_mut(&mut self) -> &mut [MaybeUninit<T>] {
1573 &mut *AsMut::<[MaybeUninit<T>; N]>::as_mut(self)
1574 }
1575}
1576
1577#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")]
1578impl<T, const N: usize> From<MaybeUninit<[T; N]>> for [MaybeUninit<T>; N] {
1579 #[inline]
1580 fn from(arr: MaybeUninit<[T; N]>) -> Self {
1581 arr.transpose()
1582 }
1583}
1584
15351585impl<T, const N: usize> [MaybeUninit<T>; N] {
15361586 /// Transposes a `[MaybeUninit<T>; N]` into a `MaybeUninit<[T; N]>`.
15371587 ///
library/core/src/slice/iter.rs+33-1
......@@ -2175,7 +2175,7 @@ unsafe impl<T> Sync for ChunksExactMut<'_, T> where T: Sync {}
21752175///
21762176/// [`array_windows`]: slice::array_windows
21772177/// [slices]: slice
2178#[derive(Debug, Clone, Copy)]
2178#[derive(Debug)]
21792179#[stable(feature = "array_windows", since = "1.94.0")]
21802180#[must_use = "iterators are lazy and do nothing unless consumed"]
21812181pub struct ArrayWindows<'a, T: 'a, const N: usize> {
......@@ -2189,6 +2189,14 @@ impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> {
21892189 }
21902190}
21912191
2192// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
2193#[stable(feature = "array_windows", since = "1.94.0")]
2194impl<T, const N: usize> Clone for ArrayWindows<'_, T, N> {
2195 fn clone(&self) -> Self {
2196 Self { v: self.v }
2197 }
2198}
2199
21922200#[stable(feature = "array_windows", since = "1.94.0")]
21932201impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {
21942202 type Item = &'a [T; N];
......@@ -2224,6 +2232,14 @@ impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {
22242232 fn last(self) -> Option<Self::Item> {
22252233 self.v.last_chunk()
22262234 }
2235
2236 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
2237 // SAFETY: since the caller guarantees that `idx` is in bounds,
2238 // which means that `idx` cannot overflow an `isize`, and the
2239 // "slice" created by `cast_array` is a subslice of `self.v`
2240 // thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
2241 unsafe { &*self.v.as_ptr().add(idx).cast_array() }
2242 }
22272243}
22282244
22292245#[stable(feature = "array_windows", since = "1.94.0")]
......@@ -2252,6 +2268,22 @@ impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> {
22522268 }
22532269}
22542270
2271#[unstable(feature = "trusted_len", issue = "37572")]
2272unsafe impl<T, const N: usize> TrustedLen for ArrayWindows<'_, T, N> {}
2273
2274#[stable(feature = "array_windows", since = "1.94.0")]
2275impl<T, const N: usize> FusedIterator for ArrayWindows<'_, T, N> {}
2276
2277#[doc(hidden)]
2278#[unstable(feature = "trusted_random_access", issue = "none")]
2279unsafe impl<T, const N: usize> TrustedRandomAccess for ArrayWindows<'_, T, N> {}
2280
2281#[doc(hidden)]
2282#[unstable(feature = "trusted_random_access", issue = "none")]
2283unsafe impl<T, const N: usize> TrustedRandomAccessNoCoerce for ArrayWindows<'_, T, N> {
2284 const MAY_HAVE_SIDE_EFFECT: bool = false;
2285}
2286
22552287/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
22562288/// time), starting at the end of the slice.
22572289///
library/proc_macro/src/bridge/client.rs+2-2
......@@ -121,7 +121,7 @@ macro_rules! define_client_side {
121121 }
122122 }
123123}
124with_api!(self, define_client_side);
124with_api!(define_client_side, TokenStream, Span, Symbol);
125125
126126struct Bridge<'a> {
127127 /// Reusable buffer (only `clear`-ed, never shrunk), primarily
......@@ -129,7 +129,7 @@ struct Bridge<'a> {
129129 cached_buffer: Buffer,
130130
131131 /// Server-side function that the client uses to make requests.
132 dispatch: closure::Closure<'a, Buffer, Buffer>,
132 dispatch: closure::Closure<'a>,
133133
134134 /// Provided globals for this macro expansion.
135135 globals: ExpnGlobals<Span>,
library/proc_macro/src/bridge/closure.rs+11-9
......@@ -1,10 +1,12 @@
1//! Closure type (equivalent to `&mut dyn FnMut(A) -> R`) that's `repr(C)`.
1//! Closure type (equivalent to `&mut dyn FnMut(Buffer) -> Buffer`) that's `repr(C)`.
22
33use std::marker::PhantomData;
44
5use super::Buffer;
6
57#[repr(C)]
6pub(super) struct Closure<'a, A, R> {
7 call: unsafe extern "C" fn(*mut Env, A) -> R,
8pub(super) struct Closure<'a> {
9 call: extern "C" fn(*mut Env, Buffer) -> Buffer,
810 env: *mut Env,
911 // Prevent Send and Sync impls.
1012 //
......@@ -14,17 +16,17 @@ pub(super) struct Closure<'a, A, R> {
1416
1517struct Env;
1618
17impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> {
19impl<'a, F: FnMut(Buffer) -> Buffer> From<&'a mut F> for Closure<'a> {
1820 fn from(f: &'a mut F) -> Self {
19 unsafe extern "C" fn call<A, R, F: FnMut(A) -> R>(env: *mut Env, arg: A) -> R {
21 extern "C" fn call<F: FnMut(Buffer) -> Buffer>(env: *mut Env, arg: Buffer) -> Buffer {
2022 unsafe { (*(env as *mut _ as *mut F))(arg) }
2123 }
22 Closure { call: call::<A, R, F>, env: f as *mut _ as *mut Env, _marker: PhantomData }
24 Closure { call: call::<F>, env: f as *mut _ as *mut Env, _marker: PhantomData }
2325 }
2426}
2527
26impl<'a, A, R> Closure<'a, A, R> {
27 pub(super) fn call(&mut self, arg: A) -> R {
28 unsafe { (self.call)(self.env, arg) }
28impl<'a> Closure<'a> {
29 pub(super) fn call(&mut self, arg: Buffer) -> Buffer {
30 (self.call)(self.env, arg)
2931 }
3032}
library/proc_macro/src/bridge/mod.rs+54-56
......@@ -18,71 +18,67 @@ use crate::{Delimiter, Level};
1818/// Higher-order macro describing the server RPC API, allowing automatic
1919/// generation of type-safe Rust APIs, both client-side and server-side.
2020///
21/// `with_api!(MySelf, my_macro)` expands to:
21/// `with_api!(my_macro, MyTokenStream, MySpan, MySymbol)` expands to:
2222/// ```rust,ignore (pseudo-code)
2323/// my_macro! {
24/// fn lit_character(ch: char) -> MySelf::Literal;
25/// fn lit_span(lit: &MySelf::Literal) -> MySelf::Span;
26/// fn lit_set_span(lit: &mut MySelf::Literal, span: MySelf::Span);
24/// fn ts_clone(stream: &MyTokenStream) -> MyTokenStream;
25/// fn span_debug(span: &MySpan) -> String;
2726/// // ...
2827/// }
2928/// ```
3029///
31/// The first argument serves to customize the argument/return types,
32/// to enable several different usecases:
33///
34/// If `MySelf` is just `Self`, then the types are only valid inside
35/// a trait or a trait impl, where the trait has associated types
36/// for each of the API types. If non-associated types are desired,
37/// a module name (`self` in practice) can be used instead of `Self`.
30/// The second (`TokenStream`), third (`Span`) and fourth (`Symbol`)
31/// argument serve to customize the argument/return types that need
32/// special handling, to enable several different representations of
33/// these types.
3834macro_rules! with_api {
39 ($S:ident, $m:ident) => {
35 ($m:ident, $TokenStream: path, $Span: path, $Symbol: path) => {
4036 $m! {
4137 fn injected_env_var(var: &str) -> Option<String>;
4238 fn track_env_var(var: &str, value: Option<&str>);
4339 fn track_path(path: &str);
44 fn literal_from_str(s: &str) -> Result<Literal<$S::Span, $S::Symbol>, ()>;
45 fn emit_diagnostic(diagnostic: Diagnostic<$S::Span>);
46
47 fn ts_drop(stream: $S::TokenStream);
48 fn ts_clone(stream: &$S::TokenStream) -> $S::TokenStream;
49 fn ts_is_empty(stream: &$S::TokenStream) -> bool;
50 fn ts_expand_expr(stream: &$S::TokenStream) -> Result<$S::TokenStream, ()>;
51 fn ts_from_str(src: &str) -> $S::TokenStream;
52 fn ts_to_string(stream: &$S::TokenStream) -> String;
40 fn literal_from_str(s: &str) -> Result<Literal<$Span, $Symbol>, ()>;
41 fn emit_diagnostic(diagnostic: Diagnostic<$Span>);
42
43 fn ts_drop(stream: $TokenStream);
44 fn ts_clone(stream: &$TokenStream) -> $TokenStream;
45 fn ts_is_empty(stream: &$TokenStream) -> bool;
46 fn ts_expand_expr(stream: &$TokenStream) -> Result<$TokenStream, ()>;
47 fn ts_from_str(src: &str) -> $TokenStream;
48 fn ts_to_string(stream: &$TokenStream) -> String;
5349 fn ts_from_token_tree(
54 tree: TokenTree<$S::TokenStream, $S::Span, $S::Symbol>,
55 ) -> $S::TokenStream;
50 tree: TokenTree<$TokenStream, $Span, $Symbol>,
51 ) -> $TokenStream;
5652 fn ts_concat_trees(
57 base: Option<$S::TokenStream>,
58 trees: Vec<TokenTree<$S::TokenStream, $S::Span, $S::Symbol>>,
59 ) -> $S::TokenStream;
53 base: Option<$TokenStream>,
54 trees: Vec<TokenTree<$TokenStream, $Span, $Symbol>>,
55 ) -> $TokenStream;
6056 fn ts_concat_streams(
61 base: Option<$S::TokenStream>,
62 streams: Vec<$S::TokenStream>,
63 ) -> $S::TokenStream;
57 base: Option<$TokenStream>,
58 streams: Vec<$TokenStream>,
59 ) -> $TokenStream;
6460 fn ts_into_trees(
65 stream: $S::TokenStream
66 ) -> Vec<TokenTree<$S::TokenStream, $S::Span, $S::Symbol>>;
67
68 fn span_debug(span: $S::Span) -> String;
69 fn span_parent(span: $S::Span) -> Option<$S::Span>;
70 fn span_source(span: $S::Span) -> $S::Span;
71 fn span_byte_range(span: $S::Span) -> Range<usize>;
72 fn span_start(span: $S::Span) -> $S::Span;
73 fn span_end(span: $S::Span) -> $S::Span;
74 fn span_line(span: $S::Span) -> usize;
75 fn span_column(span: $S::Span) -> usize;
76 fn span_file(span: $S::Span) -> String;
77 fn span_local_file(span: $S::Span) -> Option<String>;
78 fn span_join(span: $S::Span, other: $S::Span) -> Option<$S::Span>;
79 fn span_subspan(span: $S::Span, start: Bound<usize>, end: Bound<usize>) -> Option<$S::Span>;
80 fn span_resolved_at(span: $S::Span, at: $S::Span) -> $S::Span;
81 fn span_source_text(span: $S::Span) -> Option<String>;
82 fn span_save_span(span: $S::Span) -> usize;
83 fn span_recover_proc_macro_span(id: usize) -> $S::Span;
84
85 fn symbol_normalize_and_validate_ident(string: &str) -> Result<$S::Symbol, ()>;
61 stream: $TokenStream
62 ) -> Vec<TokenTree<$TokenStream, $Span, $Symbol>>;
63
64 fn span_debug(span: $Span) -> String;
65 fn span_parent(span: $Span) -> Option<$Span>;
66 fn span_source(span: $Span) -> $Span;
67 fn span_byte_range(span: $Span) -> Range<usize>;
68 fn span_start(span: $Span) -> $Span;
69 fn span_end(span: $Span) -> $Span;
70 fn span_line(span: $Span) -> usize;
71 fn span_column(span: $Span) -> usize;
72 fn span_file(span: $Span) -> String;
73 fn span_local_file(span: $Span) -> Option<String>;
74 fn span_join(span: $Span, other: $Span) -> Option<$Span>;
75 fn span_subspan(span: $Span, start: Bound<usize>, end: Bound<usize>) -> Option<$Span>;
76 fn span_resolved_at(span: $Span, at: $Span) -> $Span;
77 fn span_source_text(span: $Span) -> Option<String>;
78 fn span_save_span(span: $Span) -> usize;
79 fn span_recover_proc_macro_span(id: usize) -> $Span;
80
81 fn symbol_normalize_and_validate_ident(string: &str) -> Result<$Symbol, ()>;
8682 }
8783 };
8884}
......@@ -126,7 +122,7 @@ pub struct BridgeConfig<'a> {
126122 input: Buffer,
127123
128124 /// Server-side function that the client uses to make requests.
129 dispatch: closure::Closure<'a, Buffer, Buffer>,
125 dispatch: closure::Closure<'a>,
130126
131127 /// If 'true', always invoke the default panic hook
132128 force_show_panics: bool,
......@@ -146,7 +142,7 @@ macro_rules! declare_tags {
146142 rpc_encode_decode!(enum ApiTags { $($method),* });
147143 }
148144}
149with_api!(self, declare_tags);
145with_api!(declare_tags, __, __, __);
150146
151147/// Helper to wrap associated types to allow trait impl dispatch.
152148/// That is, normally a pair of impls for `T::Foo` and `T::Bar`
......@@ -173,7 +169,7 @@ impl<T, M> Mark for Marked<T, M> {
173169 self.value
174170 }
175171}
176impl<'a, T, M> Mark for &'a Marked<T, M> {
172impl<'a, T> Mark for &'a Marked<T, client::TokenStream> {
177173 type Unmarked = &'a T;
178174 fn mark(_: Self::Unmarked) -> Self {
179175 unreachable!()
......@@ -220,6 +216,8 @@ mark_noop! {
220216 Delimiter,
221217 LitKind,
222218 Level,
219 Bound<usize>,
220 Range<usize>,
223221}
224222
225223rpc_encode_decode!(
......@@ -318,7 +316,7 @@ macro_rules! compound_traits {
318316 };
319317}
320318
321compound_traits!(
319rpc_encode_decode!(
322320 enum Bound<T> {
323321 Included(x),
324322 Excluded(x),
......@@ -390,7 +388,7 @@ pub struct Literal<Span, Symbol> {
390388 pub span: Span,
391389}
392390
393compound_traits!(struct Literal<Sp, Sy> { kind, symbol, suffix, span });
391compound_traits!(struct Literal<Span, Symbol> { kind, symbol, suffix, span });
394392
395393#[derive(Clone)]
396394pub enum TokenTree<TokenStream, Span, Symbol> {
......@@ -434,6 +432,6 @@ compound_traits!(
434432 struct ExpnGlobals<Span> { def_site, call_site, mixed_site }
435433);
436434
437compound_traits!(
435rpc_encode_decode!(
438436 struct Range<T> { start, end }
439437);
library/proc_macro/src/bridge/rpc.rs+26-34
......@@ -52,45 +52,37 @@ macro_rules! rpc_encode_decode {
5252 }
5353 };
5454 (enum $name:ident $(<$($T:ident),+>)? { $($variant:ident $(($field:ident))*),* $(,)? }) => {
55 impl<S, $($($T: Encode<S>),+)?> Encode<S> for $name $(<$($T),+>)? {
56 fn encode(self, w: &mut Buffer, s: &mut S) {
57 // HACK(eddyb): `Tag` enum duplicated between the
58 // two impls as there's no other place to stash it.
59 #[allow(non_camel_case_types)]
60 #[repr(u8)]
61 enum Tag { $($variant),* }
62
63 match self {
64 $($name::$variant $(($field))* => {
65 (Tag::$variant as u8).encode(w, s);
66 $($field.encode(w, s);)*
67 })*
55 #[allow(non_upper_case_globals, non_camel_case_types)]
56 const _: () = {
57 #[repr(u8)] enum Tag { $($variant),* }
58
59 $(const $variant: u8 = Tag::$variant as u8;)*
60
61 impl<S, $($($T: Encode<S>),+)?> Encode<S> for $name $(<$($T),+>)? {
62 fn encode(self, w: &mut Buffer, s: &mut S) {
63 match self {
64 $($name::$variant $(($field))* => {
65 $variant.encode(w, s);
66 $($field.encode(w, s);)*
67 })*
68 }
6869 }
6970 }
70 }
7171
72 impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S>
73 for $name $(<$($T),+>)?
74 {
75 fn decode(r: &mut &'a [u8], s: &mut S) -> Self {
76 // HACK(eddyb): `Tag` enum duplicated between the
77 // two impls as there's no other place to stash it.
78 #[allow(non_upper_case_globals, non_camel_case_types)]
79 mod tag {
80 #[repr(u8)] enum Tag { $($variant),* }
81
82 $(pub(crate) const $variant: u8 = Tag::$variant as u8;)*
83 }
84
85 match u8::decode(r, s) {
86 $(tag::$variant => {
87 $(let $field = Decode::decode(r, s);)*
88 $name::$variant $(($field))*
89 })*
90 _ => unreachable!(),
72 impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S>
73 for $name $(<$($T),+>)?
74 {
75 fn decode(r: &mut &'a [u8], s: &mut S) -> Self {
76 match u8::decode(r, s) {
77 $($variant => {
78 $(let $field = Decode::decode(r, s);)*
79 $name::$variant $(($field))*
80 })*
81 _ => unreachable!(),
82 }
9183 }
9284 }
93 }
85 };
9486 }
9587}
9688
library/proc_macro/src/bridge/selfless_reify.rs+22-42
......@@ -38,47 +38,27 @@
3838
3939use std::mem;
4040
41// FIXME(eddyb) this could be `trait` impls except for the `const fn` requirement.
42macro_rules! define_reify_functions {
43 ($(
44 fn $name:ident $(<$($param:ident),*>)?
45 for $(extern $abi:tt)? fn($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty;
46 )+) => {
47 $(pub(super) const fn $name<
48 $($($param,)*)?
49 F: Fn($($arg_ty),*) -> $ret_ty + Copy
50 >(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty {
51 // FIXME(eddyb) describe the `F` type (e.g. via `type_name::<F>`) once panic
52 // formatting becomes possible in `const fn`.
53 const { assert!(size_of::<F>() == 0, "selfless_reify: closure must be zero-sized"); }
54
55 $(extern $abi)? fn wrapper<
56 $($($param,)*)?
57 F: Fn($($arg_ty),*) -> $ret_ty + Copy
58 >($($arg: $arg_ty),*) -> $ret_ty {
59 let f = unsafe {
60 // SAFETY: `F` satisfies all criteria for "out of thin air"
61 // reconstructability (see module-level doc comment).
62 mem::MaybeUninit::<F>::uninit().assume_init()
63 };
64 f($($arg),*)
65 }
66 let _f_proof = f;
67 wrapper::<
68 $($($param,)*)?
69 F
70 >
71 })+
41pub(super) const fn reify_to_extern_c_fn_hrt_bridge<
42 R,
43 F: Fn(super::BridgeConfig<'_>) -> R + Copy,
44>(
45 f: F,
46) -> extern "C" fn(super::BridgeConfig<'_>) -> R {
47 // FIXME(eddyb) describe the `F` type (e.g. via `type_name::<F>`) once panic
48 // formatting becomes possible in `const fn`.
49 const {
50 assert!(size_of::<F>() == 0, "selfless_reify: closure must be zero-sized");
7251 }
73}
74
75define_reify_functions! {
76 fn _reify_to_extern_c_fn_unary<A, R> for extern "C" fn(arg: A) -> R;
77
78 // HACK(eddyb) this abstraction is used with `for<'a> fn(BridgeConfig<'a>)
79 // -> T` but that doesn't work with just `reify_to_extern_c_fn_unary`
80 // because of the `fn` pointer type being "higher-ranked" (i.e. the
81 // `for<'a>` binder).
82 // FIXME(eddyb) try to remove the lifetime from `BridgeConfig`, that'd help.
83 fn reify_to_extern_c_fn_hrt_bridge<R> for extern "C" fn(bridge: super::BridgeConfig<'_>) -> R;
52 extern "C" fn wrapper<R, F: Fn(super::BridgeConfig<'_>) -> R + Copy>(
53 bridge: super::BridgeConfig<'_>,
54 ) -> R {
55 let f = unsafe {
56 // SAFETY: `F` satisfies all criteria for "out of thin air"
57 // reconstructability (see module-level doc comment).
58 mem::conjure_zst::<F>()
59 };
60 f(bridge)
61 }
62 let _f_proof = f;
63 wrapper::<R, F>
8464}
library/proc_macro/src/bridge/server.rs+10-14
......@@ -58,12 +58,12 @@ struct Dispatcher<S: Server> {
5858 server: S,
5959}
6060
61macro_rules! define_server_dispatcher_impl {
61macro_rules! define_server {
6262 (
6363 $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)*
6464 ) => {
6565 pub trait Server {
66 type TokenStream: 'static + Clone;
66 type TokenStream: 'static + Clone + Default;
6767 type Span: 'static + Copy + Eq + Hash;
6868 type Symbol: 'static;
6969
......@@ -77,22 +77,20 @@ macro_rules! define_server_dispatcher_impl {
7777
7878 $(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?;)*
7979 }
80 }
81}
82with_api!(define_server, Self::TokenStream, Self::Span, Self::Symbol);
8083
84macro_rules! define_dispatcher {
85 (
86 $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)*
87 ) => {
8188 // FIXME(eddyb) `pub` only for `ExecutionStrategy` below.
8289 pub trait DispatcherTrait {
83 // HACK(eddyb) these are here to allow `Self::$name` to work below.
84 type TokenStream;
85 type Span;
86 type Symbol;
87
8890 fn dispatch(&mut self, buf: Buffer) -> Buffer;
8991 }
9092
9193 impl<S: Server> DispatcherTrait for Dispatcher<S> {
92 type TokenStream = MarkedTokenStream<S>;
93 type Span = MarkedSpan<S>;
94 type Symbol = MarkedSymbol<S>;
95
9694 fn dispatch(&mut self, mut buf: Buffer) -> Buffer {
9795 let Dispatcher { handle_store, server } = self;
9896
......@@ -127,7 +125,7 @@ macro_rules! define_server_dispatcher_impl {
127125 }
128126 }
129127}
130with_api!(Self, define_server_dispatcher_impl);
128with_api!(define_dispatcher, MarkedTokenStream<S>, MarkedSpan<S>, MarkedSymbol<S>);
131129
132130pub trait ExecutionStrategy {
133131 fn run_bridge_and_client(
......@@ -312,7 +310,6 @@ impl client::Client<crate::TokenStream, crate::TokenStream> {
312310 ) -> Result<S::TokenStream, PanicMessage>
313311 where
314312 S: Server,
315 S::TokenStream: Default,
316313 {
317314 let client::Client { handle_counters, run, _marker } = *self;
318315 run_server(
......@@ -338,7 +335,6 @@ impl client::Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream
338335 ) -> Result<S::TokenStream, PanicMessage>
339336 where
340337 S: Server,
341 S::TokenStream: Default,
342338 {
343339 let client::Client { handle_counters, run, _marker } = *self;
344340 run_server(
library/proc_macro/src/lib.rs+1
......@@ -27,6 +27,7 @@
2727#![feature(restricted_std)]
2828#![feature(rustc_attrs)]
2929#![feature(extend_one)]
30#![feature(mem_conjure_zst)]
3031#![recursion_limit = "256"]
3132#![allow(internal_features)]
3233#![deny(ffi_unwind_calls)]
library/std/src/path.rs+14
......@@ -19,6 +19,20 @@
1919//! matter the platform or filesystem. An exception to this is made for Windows
2020//! drive letters.
2121//!
22//! ## Path normalization
23//!
24//! Several methods in this module perform basic path normalization by disregarding
25//! repeated separators, non-leading `.` components, and trailing separators. These include:
26//! - Methods for iteration, such as [`Path::components`] and [`Path::iter`]
27//! - Methods for inspection, such as [`Path::has_root`]
28//! - Comparisons using [`PartialEq`], [`PartialOrd`], and [`Ord`]
29//!
30//! [`Path::join`] and [`PathBuf::push`] also disregard trailing slashes.
31//!
32// FIXME(normalize_lexically): mention normalize_lexically once stable
33//! These methods **do not** resolve `..` components or symlinks. For full normalization
34//! including `..` resolution, use [`Path::canonicalize`] (which does access the filesystem).
35//!
2236//! ## Simple usage
2337//!
2438//! Path manipulation includes both parsing components from slices and building
src/tools/compiletest/src/common.rs+3-1
......@@ -949,7 +949,9 @@ impl TargetCfgs {
949949 // actually be changed with `-C` flags.
950950 for config in query_rustc_output(
951951 config,
952 &["--print=cfg", "--target", &config.target],
952 // `-Zunstable-options` is necessary when compiletest is running with custom targets
953 // (such as synthetic targets used to bless mir-opt tests).
954 &["-Zunstable-options", "--print=cfg", "--target", &config.target],
953955 Default::default(),
954956 )
955957 .trim()
src/tools/compiletest/src/directives/directive_names.rs+1
......@@ -249,6 +249,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
249249 "only-unix",
250250 "only-visionos",
251251 "only-wasm32",
252 "only-wasm32-unknown-emscripten",
252253 "only-wasm32-unknown-unknown",
253254 "only-wasm32-wasip1",
254255 "only-watchos",
src/tools/compiletest/src/runtest.rs+5
......@@ -1670,6 +1670,11 @@ impl<'test> TestCx<'test> {
16701670 if self.props.force_host { &*self.config.host } else { &*self.config.target };
16711671
16721672 compiler.arg(&format!("--target={}", target));
1673 if target.ends_with(".json") {
1674 // `-Zunstable-options` is necessary when compiletest is running with custom targets
1675 // (such as synthetic targets used to bless mir-opt tests).
1676 compiler.arg("-Zunstable-options");
1677 }
16731678 }
16741679 self.set_revision_flags(&mut compiler);
16751680
src/tools/rust-analyzer/Cargo.lock+15-15
......@@ -1614,9 +1614,9 @@ dependencies = [
16141614
16151615[[package]]
16161616name = "num-conv"
1617version = "0.1.0"
1617version = "0.2.0"
16181618source = "registry+https://github.com/rust-lang/crates.io-index"
1619checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
1619checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
16201620
16211621[[package]]
16221622name = "num-traits"
......@@ -2453,9 +2453,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
24532453
24542454[[package]]
24552455name = "salsa"
2456version = "0.25.2"
2456version = "0.26.0"
24572457source = "registry+https://github.com/rust-lang/crates.io-index"
2458checksum = "e2e2aa2fca57727371eeafc975acc8e6f4c52f8166a78035543f6ee1c74c2dcc"
2458checksum = "f77debccd43ba198e9cee23efd7f10330ff445e46a98a2b107fed9094a1ee676"
24592459dependencies = [
24602460 "boxcar",
24612461 "crossbeam-queue",
......@@ -2478,15 +2478,15 @@ dependencies = [
24782478
24792479[[package]]
24802480name = "salsa-macro-rules"
2481version = "0.25.2"
2481version = "0.26.0"
24822482source = "registry+https://github.com/rust-lang/crates.io-index"
2483checksum = "1bfc2a1e7bf06964105515451d728f2422dedc3a112383324a00b191a5c397a3"
2483checksum = "ea07adbf42d91cc076b7daf3b38bc8168c19eb362c665964118a89bc55ef19a5"
24842484
24852485[[package]]
24862486name = "salsa-macros"
2487version = "0.25.2"
2487version = "0.26.0"
24882488source = "registry+https://github.com/rust-lang/crates.io-index"
2489checksum = "3d844c1aa34946da46af683b5c27ec1088a3d9d84a2b837a108223fd830220e1"
2489checksum = "d16d4d8b66451b9c75ddf740b7fc8399bc7b8ba33e854a5d7526d18708f67b05"
24902490dependencies = [
24912491 "proc-macro2",
24922492 "quote",
......@@ -2914,9 +2914,9 @@ dependencies = [
29142914
29152915[[package]]
29162916name = "time"
2917version = "0.3.44"
2917version = "0.3.47"
29182918source = "registry+https://github.com/rust-lang/crates.io-index"
2919checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
2919checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
29202920dependencies = [
29212921 "deranged",
29222922 "itoa",
......@@ -2924,22 +2924,22 @@ dependencies = [
29242924 "num-conv",
29252925 "num_threads",
29262926 "powerfmt",
2927 "serde",
2927 "serde_core",
29282928 "time-core",
29292929 "time-macros",
29302930]
29312931
29322932[[package]]
29332933name = "time-core"
2934version = "0.1.6"
2934version = "0.1.8"
29352935source = "registry+https://github.com/rust-lang/crates.io-index"
2936checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
2936checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
29372937
29382938[[package]]
29392939name = "time-macros"
2940version = "0.2.24"
2940version = "0.2.27"
29412941source = "registry+https://github.com/rust-lang/crates.io-index"
2942checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
2942checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
29432943dependencies = [
29442944 "num-conv",
29452945 "time-core",
src/tools/rust-analyzer/Cargo.toml+2-4
......@@ -135,13 +135,13 @@ rayon = "1.10.0"
135135rowan = "=0.15.17"
136136# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work
137137# on impls without it
138salsa = { version = "0.25.2", default-features = false, features = [
138salsa = { version = "0.26", default-features = false, features = [
139139 "rayon",
140140 "salsa_unstable",
141141 "macros",
142142 "inventory",
143143] }
144salsa-macros = "0.25.2"
144salsa-macros = "0.26"
145145semver = "1.0.26"
146146serde = { version = "1.0.219" }
147147serde_derive = { version = "1.0.219" }
......@@ -192,8 +192,6 @@ unused_lifetimes = "warn"
192192unreachable_pub = "warn"
193193
194194[workspace.lints.clippy]
195# FIXME Remove the tidy test once the lint table is stable
196
197195## lint groups
198196complexity = { level = "warn", priority = -1 }
199197correctness = { level = "deny", priority = -1 }
src/tools/rust-analyzer/bench_data/glorious_old_parser+1-17
......@@ -724,7 +724,7 @@ impl<'a> Parser<'a> {
724724 // {foo(bar {}}
725725 // - ^
726726 // | |
727 // | help: `)` may belong here (FIXME: #58270)
727 // | help: `)` may belong here
728728 // |
729729 // unclosed delimiter
730730 if let Some(sp) = unmatched.unclosed_span {
......@@ -3217,7 +3217,6 @@ impl<'a> Parser<'a> {
32173217
32183218 }
32193219 _ => {
3220 // FIXME Could factor this out into non_fatal_unexpected or something.
32213220 let actual = self.this_token_to_string();
32223221 self.span_err(self.span, &format!("unexpected token: `{}`", actual));
32233222 }
......@@ -5250,7 +5249,6 @@ impl<'a> Parser<'a> {
52505249 }
52515250 }
52525251 } else {
5253 // FIXME: Bad copy of attrs
52545252 let old_directory_ownership =
52555253 mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
52565254 let item = self.parse_item_(attrs.clone(), false, true)?;
......@@ -5953,23 +5951,14 @@ impl<'a> Parser<'a> {
59535951 });
59545952 assoc_ty_bindings.push(span);
59555953 } else if self.check_const_arg() {
5956 // FIXME(const_generics): to distinguish between idents for types and consts,
5957 // we should introduce a GenericArg::Ident in the AST and distinguish when
5958 // lowering to the HIR. For now, idents for const args are not permitted.
5959
59605954 // Parse const argument.
59615955 let expr = if let token::OpenDelim(token::Brace) = self.token {
59625956 self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())?
59635957 } else if self.token.is_ident() {
5964 // FIXME(const_generics): to distinguish between idents for types and consts,
5965 // we should introduce a GenericArg::Ident in the AST and distinguish when
5966 // lowering to the HIR. For now, idents for const args are not permitted.
59675958 return Err(
59685959 self.fatal("identifiers may currently not be used for const generics")
59695960 );
59705961 } else {
5971 // FIXME(const_generics): this currently conflicts with emplacement syntax
5972 // with negative integer literals.
59735962 self.parse_literal_maybe_minus()?
59745963 };
59755964 let value = AnonConst {
......@@ -5991,9 +5980,6 @@ impl<'a> Parser<'a> {
59915980 }
59925981 }
59935982
5994 // FIXME: we would like to report this in ast_validation instead, but we currently do not
5995 // preserve ordering of generic parameters with respect to associated type binding, so we
5996 // lose that information after parsing.
59975983 if misplaced_assoc_ty_bindings.len() > 0 {
59985984 let mut err = self.struct_span_err(
59995985 args_lo.to(self.prev_span),
......@@ -6079,8 +6065,6 @@ impl<'a> Parser<'a> {
60796065 bounds,
60806066 }
60816067 ));
6082 // FIXME: Decide what should be used here, `=` or `==`.
6083 // FIXME: We are just dropping the binders in lifetime_defs on the floor here.
60846068 } else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
60856069 let rhs_ty = self.parse_ty()?;
60866070 where_clause.predicates.push(ast::WherePredicate::EqPredicate(
src/tools/rust-analyzer/crates/base-db/src/editioned_file_id.rs+1-1
......@@ -60,7 +60,7 @@ const _: () = {
6060 }
6161 }
6262
63 impl zalsa_struct_::HashEqLike<WithoutCrate> for EditionedFileIdData {
63 impl zalsa_::HashEqLike<WithoutCrate> for EditionedFileIdData {
6464 #[inline]
6565 fn hash<H: Hasher>(&self, state: &mut H) {
6666 Hash::hash(self, state);
src/tools/rust-analyzer/crates/edition/src/lib.rs-2
......@@ -16,8 +16,6 @@ impl Edition {
1616 pub const DEFAULT: Edition = Edition::Edition2015;
1717 pub const LATEST: Edition = Edition::Edition2024;
1818 pub const CURRENT: Edition = Edition::Edition2024;
19 /// The current latest stable edition, note this is usually not the right choice in code.
20 pub const CURRENT_FIXME: Edition = Edition::Edition2024;
2119
2220 pub fn from_u32(u32: u32) -> Edition {
2321 match u32 {
src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs+68-14
......@@ -426,7 +426,7 @@ pub struct ExprCollector<'db> {
426426 /// and we need to find the current definition. So we track the number of definitions we saw.
427427 current_block_legacy_macro_defs_count: FxHashMap<Name, usize>,
428428
429 current_try_block_label: Option<LabelId>,
429 current_try_block: Option<TryBlock>,
430430
431431 label_ribs: Vec<LabelRib>,
432432 unowned_bindings: Vec<BindingId>,
......@@ -472,6 +472,13 @@ enum Awaitable {
472472 No(&'static str),
473473}
474474
475enum TryBlock {
476 // `try { ... }`
477 Homogeneous { label: LabelId },
478 // `try bikeshed Ty { ... }`
479 Heterogeneous { label: LabelId },
480}
481
475482#[derive(Debug, Default)]
476483struct BindingList {
477484 map: FxHashMap<(Name, HygieneId), BindingId>,
......@@ -532,7 +539,7 @@ impl<'db> ExprCollector<'db> {
532539 lang_items: OnceCell::new(),
533540 store: ExpressionStoreBuilder::default(),
534541 expander,
535 current_try_block_label: None,
542 current_try_block: None,
536543 is_lowering_coroutine: false,
537544 label_ribs: Vec::new(),
538545 unowned_bindings: Vec::new(),
......@@ -1069,7 +1076,9 @@ impl<'db> ExprCollector<'db> {
10691076 self.alloc_expr(Expr::Let { pat, expr }, syntax_ptr)
10701077 }
10711078 ast::Expr::BlockExpr(e) => match e.modifier() {
1072 Some(ast::BlockModifier::Try(_)) => self.desugar_try_block(e),
1079 Some(ast::BlockModifier::Try { try_token: _, bikeshed_token: _, result_type }) => {
1080 self.desugar_try_block(e, result_type)
1081 }
10731082 Some(ast::BlockModifier::Unsafe(_)) => {
10741083 self.collect_block_(e, |id, statements, tail| Expr::Unsafe {
10751084 id,
......@@ -1344,7 +1353,7 @@ impl<'db> ExprCollector<'db> {
13441353 .map(|it| this.lower_type_ref_disallow_impl_trait(it));
13451354
13461355 let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine);
1347 let prev_try_block_label = this.current_try_block_label.take();
1356 let prev_try_block = this.current_try_block.take();
13481357
13491358 let awaitable = if e.async_token().is_some() {
13501359 Awaitable::Yes
......@@ -1369,7 +1378,7 @@ impl<'db> ExprCollector<'db> {
13691378 let capture_by =
13701379 if e.move_token().is_some() { CaptureBy::Value } else { CaptureBy::Ref };
13711380 this.is_lowering_coroutine = prev_is_lowering_coroutine;
1372 this.current_try_block_label = prev_try_block_label;
1381 this.current_try_block = prev_try_block;
13731382 this.alloc_expr(
13741383 Expr::Closure {
13751384 args: args.into(),
......@@ -1686,11 +1695,15 @@ impl<'db> ExprCollector<'db> {
16861695 /// Desugar `try { <stmts>; <expr> }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(<expr>) }`,
16871696 /// `try { <stmts>; }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(()) }`
16881697 /// and save the `<new_label>` to use it as a break target for desugaring of the `?` operator.
1689 fn desugar_try_block(&mut self, e: BlockExpr) -> ExprId {
1698 fn desugar_try_block(&mut self, e: BlockExpr, result_type: Option<ast::Type>) -> ExprId {
16901699 let try_from_output = self.lang_path(self.lang_items().TryTraitFromOutput);
16911700 let label = self.generate_new_name();
16921701 let label = self.alloc_label_desugared(Label { name: label }, AstPtr::new(&e).wrap_right());
1693 let old_label = self.current_try_block_label.replace(label);
1702 let try_block_info = match result_type {
1703 Some(_) => TryBlock::Heterogeneous { label },
1704 None => TryBlock::Homogeneous { label },
1705 };
1706 let old_try_block = self.current_try_block.replace(try_block_info);
16941707
16951708 let ptr = AstPtr::new(&e).upcast();
16961709 let (btail, expr_id) = self.with_labeled_rib(label, HygieneId::ROOT, |this| {
......@@ -1720,8 +1733,38 @@ impl<'db> ExprCollector<'db> {
17201733 unreachable!("block was lowered to non-block");
17211734 };
17221735 *tail = Some(next_tail);
1723 self.current_try_block_label = old_label;
1724 expr_id
1736 self.current_try_block = old_try_block;
1737 match result_type {
1738 Some(ty) => {
1739 // `{ let <name>: <ty> = <expr>; <name> }`
1740 let name = self.generate_new_name();
1741 let type_ref = self.lower_type_ref_disallow_impl_trait(ty);
1742 let binding = self.alloc_binding(
1743 name.clone(),
1744 BindingAnnotation::Unannotated,
1745 HygieneId::ROOT,
1746 );
1747 let pat = self.alloc_pat_desugared(Pat::Bind { id: binding, subpat: None });
1748 self.add_definition_to_binding(binding, pat);
1749 let tail_expr =
1750 self.alloc_expr_desugared_with_ptr(Expr::Path(Path::from(name)), ptr);
1751 self.alloc_expr_desugared_with_ptr(
1752 Expr::Block {
1753 id: None,
1754 statements: Box::new([Statement::Let {
1755 pat,
1756 type_ref: Some(type_ref),
1757 initializer: Some(expr_id),
1758 else_branch: None,
1759 }]),
1760 tail: Some(tail_expr),
1761 label: None,
1762 },
1763 ptr,
1764 )
1765 }
1766 None => expr_id,
1767 }
17251768 }
17261769
17271770 /// Desugar `ast::WhileExpr` from: `[opt_ident]: while <cond> <body>` into:
......@@ -1863,6 +1906,8 @@ impl<'db> ExprCollector<'db> {
18631906 /// ControlFlow::Continue(val) => val,
18641907 /// ControlFlow::Break(residual) =>
18651908 /// // If there is an enclosing `try {...}`:
1909 /// break 'catch_target Residual::into_try_type(residual),
1910 /// // If there is an enclosing `try bikeshed Ty {...}`:
18661911 /// break 'catch_target Try::from_residual(residual),
18671912 /// // Otherwise:
18681913 /// return Try::from_residual(residual),
......@@ -1873,7 +1918,6 @@ impl<'db> ExprCollector<'db> {
18731918 let try_branch = self.lang_path(lang_items.TryTraitBranch);
18741919 let cf_continue = self.lang_path(lang_items.ControlFlowContinue);
18751920 let cf_break = self.lang_path(lang_items.ControlFlowBreak);
1876 let try_from_residual = self.lang_path(lang_items.TryTraitFromResidual);
18771921 let operand = self.collect_expr_opt(e.expr());
18781922 let try_branch = self.alloc_expr(try_branch.map_or(Expr::Missing, Expr::Path), syntax_ptr);
18791923 let expr = self
......@@ -1910,13 +1954,23 @@ impl<'db> ExprCollector<'db> {
19101954 guard: None,
19111955 expr: {
19121956 let it = self.alloc_expr(Expr::Path(Path::from(break_name)), syntax_ptr);
1913 let callee = self
1914 .alloc_expr(try_from_residual.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1957 let convert_fn = match self.current_try_block {
1958 Some(TryBlock::Homogeneous { .. }) => {
1959 self.lang_path(lang_items.ResidualIntoTryType)
1960 }
1961 Some(TryBlock::Heterogeneous { .. }) | None => {
1962 self.lang_path(lang_items.TryTraitFromResidual)
1963 }
1964 };
1965 let callee =
1966 self.alloc_expr(convert_fn.map_or(Expr::Missing, Expr::Path), syntax_ptr);
19151967 let result =
19161968 self.alloc_expr(Expr::Call { callee, args: Box::new([it]) }, syntax_ptr);
19171969 self.alloc_expr(
1918 match self.current_try_block_label {
1919 Some(label) => Expr::Break { expr: Some(result), label: Some(label) },
1970 match self.current_try_block {
1971 Some(
1972 TryBlock::Heterogeneous { label } | TryBlock::Homogeneous { label },
1973 ) => Expr::Break { expr: Some(result), label: Some(label) },
19201974 None => Expr::Return { expr: Some(result) },
19211975 },
19221976 syntax_ptr,
src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs+18
......@@ -893,6 +893,24 @@ impl ItemScope {
893893 self.macros.get_mut(name).expect("tried to update visibility of non-existent macro");
894894 res.vis = vis;
895895 }
896
897 pub(crate) fn update_def_types(&mut self, name: &Name, def: ModuleDefId, vis: Visibility) {
898 let res = self.types.get_mut(name).expect("tried to update def of non-existent type");
899 res.def = def;
900 res.vis = vis;
901 }
902
903 pub(crate) fn update_def_values(&mut self, name: &Name, def: ModuleDefId, vis: Visibility) {
904 let res = self.values.get_mut(name).expect("tried to update def of non-existent value");
905 res.def = def;
906 res.vis = vis;
907 }
908
909 pub(crate) fn update_def_macros(&mut self, name: &Name, def: MacroId, vis: Visibility) {
910 let res = self.macros.get_mut(name).expect("tried to update def of non-existent macro");
911 res.def = def;
912 res.vis = vis;
913 }
896914}
897915
898916impl PerNs {
src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs+1
......@@ -456,6 +456,7 @@ language_item_table! { LangItems =>
456456 TryTraitFromOutput, sym::from_output, FunctionId;
457457 TryTraitBranch, sym::branch, FunctionId;
458458 TryTraitFromYeet, sym::from_yeet, FunctionId;
459 ResidualIntoTryType, sym::into_try_type, FunctionId;
459460
460461 PointerLike, sym::pointer_like, TraitId;
461462
src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs+52-25
......@@ -1209,42 +1209,69 @@ impl<'db> DefCollector<'db> {
12091209 // `ItemScope::push_res_with_import()`.
12101210 if let Some(def) = defs.types
12111211 && let Some(prev_def) = prev_defs.types
1212 && def.def == prev_def.def
1213 && self.from_glob_import.contains_type(module_id, name.clone())
1214 && def.vis != prev_def.vis
1215 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
12161212 {
1217 changed = true;
1218 // This import is being handled here, don't pass it down to
1219 // `ItemScope::push_res_with_import()`.
1220 defs.types = None;
1221 self.def_map.modules[module_id].scope.update_visibility_types(name, def.vis);
1213 if def.def == prev_def.def
1214 && self.from_glob_import.contains_type(module_id, name.clone())
1215 && def.vis != prev_def.vis
1216 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1217 {
1218 changed = true;
1219 // This import is being handled here, don't pass it down to
1220 // `ItemScope::push_res_with_import()`.
1221 defs.types = None;
1222 self.def_map.modules[module_id].scope.update_visibility_types(name, def.vis);
1223 }
1224 // When the source module's definition changed (e.g., due to an explicit import
1225 // shadowing a glob), propagate the new definition to modules that glob-import from it.
1226 // We check that the previous definition came from the same glob import to avoid
1227 // incorrectly overwriting definitions from different glob sources.
1228 //
1229 // Note this is not a perfect fix, but it makes
1230 // https://github.com/rust-lang/rust-analyzer/issues/19224 work for now until we
1231 // implement a proper glob graph
1232 else if def.def != prev_def.def && prev_def.import == def_import_type {
1233 changed = true;
1234 defs.types = None;
1235 self.def_map.modules[module_id].scope.update_def_types(name, def.def, def.vis);
1236 }
12221237 }
12231238
12241239 if let Some(def) = defs.values
12251240 && let Some(prev_def) = prev_defs.values
1226 && def.def == prev_def.def
1227 && self.from_glob_import.contains_value(module_id, name.clone())
1228 && def.vis != prev_def.vis
1229 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
12301241 {
1231 changed = true;
1232 // See comment above.
1233 defs.values = None;
1234 self.def_map.modules[module_id].scope.update_visibility_values(name, def.vis);
1242 if def.def == prev_def.def
1243 && self.from_glob_import.contains_value(module_id, name.clone())
1244 && def.vis != prev_def.vis
1245 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1246 {
1247 changed = true;
1248 defs.values = None;
1249 self.def_map.modules[module_id].scope.update_visibility_values(name, def.vis);
1250 } else if def.def != prev_def.def
1251 && prev_def.import.map(ImportOrExternCrate::from) == def_import_type
1252 {
1253 changed = true;
1254 defs.values = None;
1255 self.def_map.modules[module_id].scope.update_def_values(name, def.def, def.vis);
1256 }
12351257 }
12361258
12371259 if let Some(def) = defs.macros
12381260 && let Some(prev_def) = prev_defs.macros
1239 && def.def == prev_def.def
1240 && self.from_glob_import.contains_macro(module_id, name.clone())
1241 && def.vis != prev_def.vis
1242 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
12431261 {
1244 changed = true;
1245 // See comment above.
1246 defs.macros = None;
1247 self.def_map.modules[module_id].scope.update_visibility_macros(name, def.vis);
1262 if def.def == prev_def.def
1263 && self.from_glob_import.contains_macro(module_id, name.clone())
1264 && def.vis != prev_def.vis
1265 && def.vis.max(self.db, prev_def.vis, &self.def_map) == Some(def.vis)
1266 {
1267 changed = true;
1268 defs.macros = None;
1269 self.def_map.modules[module_id].scope.update_visibility_macros(name, def.vis);
1270 } else if def.def != prev_def.def && prev_def.import == def_import_type {
1271 changed = true;
1272 defs.macros = None;
1273 self.def_map.modules[module_id].scope.update_def_macros(name, def.def, def.vis);
1274 }
12481275 }
12491276 }
12501277
src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs+11-8
......@@ -830,15 +830,18 @@ fn include_bytes_expand(
830830 span: Span,
831831) -> ExpandResult<tt::TopSubtree> {
832832 // FIXME: actually read the file here if the user asked for macro expansion
833 let res = tt::TopSubtree::invisible_from_leaves(
833 let underscore = sym::underscore;
834 let zero = tt::Literal {
835 text_and_suffix: sym::_0_u8,
834836 span,
835 [tt::Leaf::Literal(tt::Literal {
836 text_and_suffix: Symbol::empty(),
837 span,
838 kind: tt::LitKind::ByteStrRaw(1),
839 suffix_len: 0,
840 })],
841 );
837 kind: tt::LitKind::Integer,
838 suffix_len: 3,
839 };
840 // We don't use a real length since we can't know the file length, so we use an underscore
841 // to infer it.
842 let res = quote! {span =>
843 &[#zero; #underscore]
844 };
842845 ExpandResult::ok(res)
843846}
844847
src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs+1-1
......@@ -133,7 +133,7 @@ pub fn impl_trait<'db>(
133133 }
134134}
135135
136#[salsa::tracked(returns(ref), unsafe(non_update_types))]
136#[salsa::tracked(returns(ref))]
137137pub fn predicates<'db>(db: &'db dyn HirDatabase, impl_: BuiltinDeriveImplId) -> GenericPredicates {
138138 let loc = impl_.loc(db);
139139 let generic_params = GenericParams::new(db, loc.adt.into());
src/tools/rust-analyzer/crates/hir-ty/src/display.rs+95-104
......@@ -12,7 +12,6 @@ use either::Either;
1212use hir_def::{
1313 FindPathConfig, GenericDefId, GenericParamId, HasModule, LocalFieldId, Lookup, ModuleDefId,
1414 ModuleId, TraitId,
15 db::DefDatabase,
1615 expr_store::{ExpressionStore, path::Path},
1716 find_path::{self, PrefixKind},
1817 hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
......@@ -100,6 +99,9 @@ pub struct HirFormatter<'a, 'db> {
10099 display_kind: DisplayKind,
101100 display_target: DisplayTarget,
102101 bounds_formatting_ctx: BoundsFormattingCtx<'db>,
102 /// Whether formatting `impl Trait1 + Trait2` or `dyn Trait1 + Trait2` needs parentheses around it,
103 /// for example when formatting `&(impl Trait1 + Trait2)`.
104 trait_bounds_need_parens: bool,
103105}
104106
105107// FIXME: To consider, ref and dyn trait lifetimes can be omitted if they are `'_`, path args should
......@@ -331,6 +333,7 @@ pub trait HirDisplay<'db> {
331333 show_container_bounds: false,
332334 display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
333335 bounds_formatting_ctx: Default::default(),
336 trait_bounds_need_parens: false,
334337 }) {
335338 Ok(()) => {}
336339 Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
......@@ -566,6 +569,7 @@ impl<'db, T: HirDisplay<'db>> HirDisplayWrapper<'_, 'db, T> {
566569 show_container_bounds: self.show_container_bounds,
567570 display_lifetimes: self.display_lifetimes,
568571 bounds_formatting_ctx: Default::default(),
572 trait_bounds_need_parens: false,
569573 })
570574 }
571575
......@@ -612,7 +616,11 @@ impl<'db, T: HirDisplay<'db> + Internable> HirDisplay<'db> for Interned<T> {
612616 }
613617}
614618
615fn write_projection<'db>(f: &mut HirFormatter<'_, 'db>, alias: &AliasTy<'db>) -> Result {
619fn write_projection<'db>(
620 f: &mut HirFormatter<'_, 'db>,
621 alias: &AliasTy<'db>,
622 needs_parens_if_multi: bool,
623) -> Result {
616624 if f.should_truncate() {
617625 return write!(f, "{TYPE_HINT_TRUNCATION}");
618626 }
......@@ -650,6 +658,7 @@ fn write_projection<'db>(f: &mut HirFormatter<'_, 'db>, alias: &AliasTy<'db>) ->
650658 Either::Left(Ty::new_alias(f.interner, AliasTyKind::Projection, *alias)),
651659 &bounds,
652660 SizedByDefault::NotSized,
661 needs_parens_if_multi,
653662 )
654663 });
655664 }
......@@ -1056,7 +1065,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
10561065 return write!(f, "{TYPE_HINT_TRUNCATION}");
10571066 }
10581067
1059 use TyKind;
1068 let trait_bounds_need_parens = mem::replace(&mut f.trait_bounds_need_parens, false);
10601069 match self.kind() {
10611070 TyKind::Never => write!(f, "!")?,
10621071 TyKind::Str => write!(f, "str")?,
......@@ -1077,103 +1086,34 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
10771086 c.hir_fmt(f)?;
10781087 write!(f, "]")?;
10791088 }
1080 kind @ (TyKind::RawPtr(t, m) | TyKind::Ref(_, t, m)) => {
1081 if let TyKind::Ref(l, _, _) = kind {
1082 f.write_char('&')?;
1083 if f.render_region(l) {
1084 l.hir_fmt(f)?;
1085 f.write_char(' ')?;
1086 }
1087 match m {
1088 rustc_ast_ir::Mutability::Not => (),
1089 rustc_ast_ir::Mutability::Mut => f.write_str("mut ")?,
1090 }
1091 } else {
1092 write!(
1093 f,
1094 "*{}",
1095 match m {
1096 rustc_ast_ir::Mutability::Not => "const ",
1097 rustc_ast_ir::Mutability::Mut => "mut ",
1098 }
1099 )?;
1089 TyKind::Ref(l, t, m) => {
1090 f.write_char('&')?;
1091 if f.render_region(l) {
1092 l.hir_fmt(f)?;
1093 f.write_char(' ')?;
1094 }
1095 match m {
1096 rustc_ast_ir::Mutability::Not => (),
1097 rustc_ast_ir::Mutability::Mut => f.write_str("mut ")?,
11001098 }
11011099
1102 // FIXME: all this just to decide whether to use parentheses...
1103 let (preds_to_print, has_impl_fn_pred) = match t.kind() {
1104 TyKind::Dynamic(bounds, region) => {
1105 let contains_impl_fn =
1106 bounds.iter().any(|bound| match bound.skip_binder() {
1107 ExistentialPredicate::Trait(trait_ref) => {
1108 let trait_ = trait_ref.def_id.0;
1109 fn_traits(f.lang_items()).any(|it| it == trait_)
1110 }
1111 _ => false,
1112 });
1113 let render_lifetime = f.render_region(region);
1114 (bounds.len() + render_lifetime as usize, contains_impl_fn)
1115 }
1116 TyKind::Alias(AliasTyKind::Opaque, ty) => {
1117 let opaque_ty_id = match ty.def_id {
1118 SolverDefId::InternedOpaqueTyId(id) => id,
1119 _ => unreachable!(),
1120 };
1121 let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id);
1122 if let ImplTraitId::ReturnTypeImplTrait(func, _) = impl_trait_id {
1123 let data = impl_trait_id.predicates(db);
1124 let bounds =
1125 || data.iter_instantiated_copied(f.interner, ty.args.as_slice());
1126 let mut len = bounds().count();
1127
1128 // Don't count Sized but count when it absent
1129 // (i.e. when explicit ?Sized bound is set).
1130 let default_sized = SizedByDefault::Sized { anchor: func.krate(db) };
1131 let sized_bounds = bounds()
1132 .filter(|b| {
1133 matches!(
1134 b.kind().skip_binder(),
1135 ClauseKind::Trait(trait_ref)
1136 if default_sized.is_sized_trait(
1137 trait_ref.def_id().0,
1138 db,
1139 ),
1140 )
1141 })
1142 .count();
1143 match sized_bounds {
1144 0 => len += 1,
1145 _ => {
1146 len = len.saturating_sub(sized_bounds);
1147 }
1148 }
1149
1150 let contains_impl_fn = bounds().any(|bound| {
1151 if let ClauseKind::Trait(trait_ref) = bound.kind().skip_binder() {
1152 let trait_ = trait_ref.def_id().0;
1153 fn_traits(f.lang_items()).any(|it| it == trait_)
1154 } else {
1155 false
1156 }
1157 });
1158 (len, contains_impl_fn)
1159 } else {
1160 (0, false)
1161 }
1100 f.trait_bounds_need_parens = true;
1101 t.hir_fmt(f)?;
1102 f.trait_bounds_need_parens = false;
1103 }
1104 TyKind::RawPtr(t, m) => {
1105 write!(
1106 f,
1107 "*{}",
1108 match m {
1109 rustc_ast_ir::Mutability::Not => "const ",
1110 rustc_ast_ir::Mutability::Mut => "mut ",
11621111 }
1163 _ => (0, false),
1164 };
1165
1166 if has_impl_fn_pred && preds_to_print <= 2 {
1167 return t.hir_fmt(f);
1168 }
1112 )?;
11691113
1170 if preds_to_print > 1 {
1171 write!(f, "(")?;
1172 t.hir_fmt(f)?;
1173 write!(f, ")")?;
1174 } else {
1175 t.hir_fmt(f)?;
1176 }
1114 f.trait_bounds_need_parens = true;
1115 t.hir_fmt(f)?;
1116 f.trait_bounds_need_parens = false;
11771117 }
11781118 TyKind::Tuple(tys) => {
11791119 if tys.len() == 1 {
......@@ -1328,7 +1268,9 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
13281268
13291269 hir_fmt_generics(f, parameters.as_slice(), Some(def.def_id().0.into()), None)?;
13301270 }
1331 TyKind::Alias(AliasTyKind::Projection, alias_ty) => write_projection(f, &alias_ty)?,
1271 TyKind::Alias(AliasTyKind::Projection, alias_ty) => {
1272 write_projection(f, &alias_ty, trait_bounds_need_parens)?
1273 }
13321274 TyKind::Foreign(alias) => {
13331275 let type_alias = db.type_alias_signature(alias.0);
13341276 f.start_location_link(alias.0.into());
......@@ -1363,6 +1305,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
13631305 Either::Left(*self),
13641306 &bounds,
13651307 SizedByDefault::Sized { anchor: krate },
1308 trait_bounds_need_parens,
13661309 )?;
13671310 }
13681311 TyKind::Closure(id, substs) => {
......@@ -1525,6 +1468,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
15251468 Either::Left(*self),
15261469 &bounds,
15271470 SizedByDefault::Sized { anchor: krate },
1471 trait_bounds_need_parens,
15281472 )?;
15291473 }
15301474 },
......@@ -1567,6 +1511,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
15671511 Either::Left(*self),
15681512 &bounds_to_display,
15691513 SizedByDefault::NotSized,
1514 trait_bounds_need_parens,
15701515 )?;
15711516 }
15721517 TyKind::Error(_) => {
......@@ -1806,11 +1751,11 @@ pub enum SizedByDefault {
18061751}
18071752
18081753impl SizedByDefault {
1809 fn is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool {
1754 fn is_sized_trait(self, trait_: TraitId, interner: DbInterner<'_>) -> bool {
18101755 match self {
18111756 Self::NotSized => false,
1812 Self::Sized { anchor } => {
1813 let sized_trait = hir_def::lang_item::lang_items(db, anchor).Sized;
1757 Self::Sized { .. } => {
1758 let sized_trait = interner.lang_items().Sized;
18141759 Some(trait_) == sized_trait
18151760 }
18161761 }
......@@ -1823,16 +1768,62 @@ pub fn write_bounds_like_dyn_trait_with_prefix<'db>(
18231768 this: Either<Ty<'db>, Region<'db>>,
18241769 predicates: &[Clause<'db>],
18251770 default_sized: SizedByDefault,
1771 needs_parens_if_multi: bool,
18261772) -> Result {
1773 let needs_parens =
1774 needs_parens_if_multi && trait_bounds_need_parens(f, this, predicates, default_sized);
1775 if needs_parens {
1776 write!(f, "(")?;
1777 }
18271778 write!(f, "{prefix}")?;
18281779 if !predicates.is_empty()
18291780 || predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
18301781 {
18311782 write!(f, " ")?;
1832 write_bounds_like_dyn_trait(f, this, predicates, default_sized)
1833 } else {
1834 Ok(())
1783 write_bounds_like_dyn_trait(f, this, predicates, default_sized)?;
1784 }
1785 if needs_parens {
1786 write!(f, ")")?;
1787 }
1788 Ok(())
1789}
1790
1791fn trait_bounds_need_parens<'db>(
1792 f: &mut HirFormatter<'_, 'db>,
1793 this: Either<Ty<'db>, Region<'db>>,
1794 predicates: &[Clause<'db>],
1795 default_sized: SizedByDefault,
1796) -> bool {
1797 // This needs to be kept in sync with `write_bounds_like_dyn_trait()`.
1798 let mut distinct_bounds = 0usize;
1799 let mut is_sized = false;
1800 for p in predicates {
1801 match p.kind().skip_binder() {
1802 ClauseKind::Trait(trait_ref) => {
1803 let trait_ = trait_ref.def_id().0;
1804 if default_sized.is_sized_trait(trait_, f.interner) {
1805 is_sized = true;
1806 if matches!(default_sized, SizedByDefault::Sized { .. }) {
1807 // Don't print +Sized, but rather +?Sized if absent.
1808 continue;
1809 }
1810 }
1811
1812 distinct_bounds += 1;
1813 }
1814 ClauseKind::TypeOutlives(to) if Either::Left(to.0) == this => distinct_bounds += 1,
1815 ClauseKind::RegionOutlives(lo) if Either::Right(lo.0) == this => distinct_bounds += 1,
1816 _ => {}
1817 }
18351818 }
1819
1820 if let SizedByDefault::Sized { .. } = default_sized
1821 && !is_sized
1822 {
1823 distinct_bounds += 1;
1824 }
1825
1826 distinct_bounds > 1
18361827}
18371828
18381829fn write_bounds_like_dyn_trait<'db>(
......@@ -1855,7 +1846,7 @@ fn write_bounds_like_dyn_trait<'db>(
18551846 match p.kind().skip_binder() {
18561847 ClauseKind::Trait(trait_ref) => {
18571848 let trait_ = trait_ref.def_id().0;
1858 if default_sized.is_sized_trait(trait_, f.db) {
1849 if default_sized.is_sized_trait(trait_, f.interner) {
18591850 is_sized = true;
18601851 if matches!(default_sized, SizedByDefault::Sized { .. }) {
18611852 // Don't print +Sized, but rather +?Sized if absent.
src/tools/rust-analyzer/crates/hir-ty/src/lower.rs+117-6
......@@ -831,6 +831,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
831831 let mut ordered_associated_types = vec![];
832832
833833 if let Some(principal_trait) = principal {
834 // Generally we should not elaborate in lowering as this can lead to cycles, but
835 // here rustc cycles as well.
834836 for clause in elaborate::elaborate(
835837 interner,
836838 [Clause::upcast_from(
......@@ -1897,7 +1899,7 @@ impl<'db> GenericPredicates {
18971899 /// Resolve the where clause(s) of an item with generics.
18981900 ///
18991901 /// Diagnostics are computed only for this item's predicates, not for parents.
1900 #[salsa::tracked(returns(ref))]
1902 #[salsa::tracked(returns(ref), cycle_result=generic_predicates_cycle_result)]
19011903 pub fn query_with_diagnostics(
19021904 db: &'db dyn HirDatabase,
19031905 def: GenericDefId,
......@@ -1906,6 +1908,20 @@ impl<'db> GenericPredicates {
19061908 }
19071909}
19081910
1911/// A cycle can occur from malformed code.
1912fn generic_predicates_cycle_result(
1913 _db: &dyn HirDatabase,
1914 _: salsa::Id,
1915 _def: GenericDefId,
1916) -> (GenericPredicates, Diagnostics) {
1917 (
1918 GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind(
1919 Clauses::default().store(),
1920 )),
1921 None,
1922 )
1923}
1924
19091925impl GenericPredicates {
19101926 #[inline]
19111927 pub(crate) fn from_explicit_own_predicates(
......@@ -2590,11 +2606,13 @@ pub(crate) fn associated_type_by_name_including_super_traits<'db>(
25902606) -> Option<(TraitRef<'db>, TypeAliasId)> {
25912607 let module = trait_ref.def_id.0.module(db);
25922608 let interner = DbInterner::new_with(db, module.krate(db));
2593 rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| {
2594 let trait_id = t.as_ref().skip_binder().def_id.0;
2595 let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?;
2596 Some((t.skip_binder(), assoc_type))
2597 })
2609 all_supertraits_trait_refs(db, trait_ref.def_id.0)
2610 .map(|t| t.instantiate(interner, trait_ref.args))
2611 .find_map(|t| {
2612 let trait_id = t.def_id.0;
2613 let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?;
2614 Some((t, assoc_type))
2615 })
25982616}
25992617
26002618pub fn associated_type_shorthand_candidates(
......@@ -2723,3 +2741,96 @@ fn named_associated_type_shorthand_candidates<'db, R>(
27232741 _ => None,
27242742 }
27252743}
2744
2745/// During lowering, elaborating supertraits can cause cycles. To avoid that, we have a separate query
2746/// to only collect supertraits.
2747///
2748/// Technically, it is possible to avoid even more cycles by only collecting the `TraitId` of supertraits
2749/// without their args. However rustc doesn't do that, so we don't either.
2750pub(crate) fn all_supertraits_trait_refs(
2751 db: &dyn HirDatabase,
2752 trait_: TraitId,
2753) -> impl ExactSizeIterator<Item = EarlyBinder<'_, TraitRef<'_>>> {
2754 let interner = DbInterner::new_no_crate(db);
2755 return all_supertraits_trait_refs_query(db, trait_).iter().map(move |trait_ref| {
2756 trait_ref.get_with(|(trait_, args)| {
2757 TraitRef::new_from_args(interner, (*trait_).into(), args.as_ref())
2758 })
2759 });
2760
2761 #[salsa_macros::tracked(returns(deref), cycle_result = all_supertraits_trait_refs_cycle_result)]
2762 pub(crate) fn all_supertraits_trait_refs_query(
2763 db: &dyn HirDatabase,
2764 trait_: TraitId,
2765 ) -> Box<[StoredEarlyBinder<(TraitId, StoredGenericArgs)>]> {
2766 let resolver = trait_.resolver(db);
2767 let signature = db.trait_signature(trait_);
2768 let mut ctx = TyLoweringContext::new(
2769 db,
2770 &resolver,
2771 &signature.store,
2772 trait_.into(),
2773 LifetimeElisionKind::AnonymousReportError,
2774 );
2775 let interner = ctx.interner;
2776
2777 let self_param_ty = Ty::new_param(
2778 interner,
2779 TypeParamId::from_unchecked(TypeOrConstParamId {
2780 parent: trait_.into(),
2781 local_id: Idx::from_raw(la_arena::RawIdx::from_u32(0)),
2782 }),
2783 0,
2784 );
2785
2786 let mut supertraits = FxHashSet::default();
2787 supertraits.insert(StoredEarlyBinder::bind((
2788 trait_,
2789 GenericArgs::identity_for_item(interner, trait_.into()).store(),
2790 )));
2791
2792 for pred in signature.generic_params.where_predicates() {
2793 let WherePredicate::TypeBound { target, bound } = pred else {
2794 continue;
2795 };
2796 let target = &signature.store[*target];
2797 if let TypeRef::TypeParam(param_id) = target
2798 && param_id.local_id().into_raw().into_u32() == 0
2799 {
2800 // This is `Self`.
2801 } else if let TypeRef::Path(path) = target
2802 && path.is_self_type()
2803 {
2804 // Also `Self`.
2805 } else {
2806 // Not `Self`!
2807 continue;
2808 }
2809
2810 ctx.lower_type_bound(bound, self_param_ty, true).for_each(|(clause, _)| {
2811 if let ClauseKind::Trait(trait_ref) = clause.kind().skip_binder() {
2812 supertraits.extend(
2813 all_supertraits_trait_refs(db, trait_ref.trait_ref.def_id.0).map(|t| {
2814 let trait_ref = t.instantiate(interner, trait_ref.trait_ref.args);
2815 StoredEarlyBinder::bind((trait_ref.def_id.0, trait_ref.args.store()))
2816 }),
2817 );
2818 }
2819 });
2820 }
2821
2822 Box::from_iter(supertraits)
2823 }
2824
2825 pub(crate) fn all_supertraits_trait_refs_cycle_result(
2826 db: &dyn HirDatabase,
2827 _: salsa::Id,
2828 trait_: TraitId,
2829 ) -> Box<[StoredEarlyBinder<(TraitId, StoredGenericArgs)>]> {
2830 let interner = DbInterner::new_no_crate(db);
2831 Box::new([StoredEarlyBinder::bind((
2832 trait_,
2833 GenericArgs::identity_for_item(interner, trait_.into()).store(),
2834 ))])
2835 }
2836}
src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs+1-1
......@@ -608,7 +608,7 @@ trait Foo {}
608608fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
609609 let _: &dyn Foo = &f;
610610 let _: &dyn Foo = g;
611 //^ expected &'? (dyn Foo + 'static), got &'? impl Foo + ?Sized
611 //^ expected &'? (dyn Foo + 'static), got &'? (impl Foo + ?Sized)
612612}
613613 "#,
614614 );
src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs+2-2
......@@ -111,7 +111,7 @@ fn test(
111111 b;
112112 //^ impl Foo
113113 c;
114 //^ &impl Foo + ?Sized
114 //^ &(impl Foo + ?Sized)
115115 d;
116116 //^ S<impl Foo>
117117 ref_any;
......@@ -192,7 +192,7 @@ fn test(
192192 b;
193193 //^ fn(impl Foo) -> impl Foo
194194 c;
195} //^ fn(&impl Foo + ?Sized) -> &impl Foo + ?Sized
195} //^ fn(&(impl Foo + ?Sized)) -> &(impl Foo + ?Sized)
196196"#,
197197 );
198198}
src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs+43
......@@ -2363,6 +2363,7 @@ fn test() {
23632363}
23642364"#,
23652365 expect![[r#"
2366 46..49 'Foo': Foo<N>
23662367 93..97 'self': Foo<N>
23672368 108..125 '{ ... }': usize
23682369 118..119 'N': usize
......@@ -2645,3 +2646,45 @@ where
26452646 "#,
26462647 );
26472648}
2649
2650#[test]
2651fn issue_21560() {
2652 check_no_mismatches(
2653 r#"
2654mod bindings {
2655 use super::*;
2656 pub type HRESULT = i32;
2657}
2658use bindings::*;
2659
2660
2661mod error {
2662 use super::*;
2663 pub fn nonzero_hresult(hr: HRESULT) -> crate::HRESULT {
2664 hr
2665 }
2666}
2667pub use error::*;
2668
2669mod hresult {
2670 use super::*;
2671 pub struct HRESULT(pub i32);
2672}
2673pub use hresult::HRESULT;
2674
2675 "#,
2676 );
2677}
2678
2679#[test]
2680fn regression_21577() {
2681 check_no_mismatches(
2682 r#"
2683pub trait FilterT<F: FilterT<F, V = Self::V> = Self> {
2684 type V;
2685
2686 fn foo() {}
2687}
2688 "#,
2689 );
2690}
src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs+19-1
......@@ -2152,10 +2152,11 @@ async fn main() {
21522152 let z: core::ops::ControlFlow<(), _> = try { () };
21532153 let w = const { 92 };
21542154 let t = 'a: { 92 };
2155 let u = try bikeshed core::ops::ControlFlow<(), _> { () };
21552156}
21562157 "#,
21572158 expect![[r#"
2158 16..193 '{ ...2 }; }': ()
2159 16..256 '{ ...) }; }': ()
21592160 26..27 'x': i32
21602161 30..43 'unsafe { 92 }': i32
21612162 39..41 '92': i32
......@@ -2176,6 +2177,13 @@ async fn main() {
21762177 176..177 't': i32
21772178 180..190 ''a: { 92 }': i32
21782179 186..188 '92': i32
2180 200..201 'u': ControlFlow<(), ()>
2181 204..253 'try bi...{ () }': ControlFlow<(), ()>
2182 204..253 'try bi...{ () }': fn from_output<ControlFlow<(), ()>>(<ControlFlow<(), ()> as Try>::Output) -> ControlFlow<(), ()>
2183 204..253 'try bi...{ () }': ControlFlow<(), ()>
2184 204..253 'try bi...{ () }': ControlFlow<(), ()>
2185 204..253 'try bi...{ () }': ControlFlow<(), ()>
2186 249..251 '()': ()
21792187 "#]],
21802188 )
21812189}
......@@ -4056,3 +4064,13 @@ fn foo() {
40564064 "#]],
40574065 );
40584066}
4067
4068#[test]
4069fn include_bytes_len_mismatch() {
4070 check_no_mismatches(
4071 r#"
4072//- minicore: include_bytes
4073static S: &[u8; 158] = include_bytes!("/foo/bar/baz.txt");
4074 "#,
4075 );
4076}
src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs+6-4
......@@ -219,14 +219,16 @@ fn test() {
219219
220220#[test]
221221fn infer_try_block() {
222 // FIXME: We should test more cases, but it currently doesn't work, since
223 // our labeled block type inference is broken.
224222 check_types(
225223 r#"
226//- minicore: try, option
224//- minicore: try, option, result, from
227225fn test() {
228226 let x: Option<_> = try { Some(2)?; };
229227 //^ Option<()>
228 let homogeneous = try { Ok::<(), u32>(())?; "hi" };
229 //^^^^^^^^^^^ Result<&'? str, u32>
230 let heterogeneous = try bikeshed Result<_, u64> { 1 };
231 //^^^^^^^^^^^^^ Result<i32, u64>
230232}
231233"#,
232234 );
......@@ -4819,7 +4821,7 @@ fn allowed3(baz: impl Baz<Assoc = Qux<impl Foo>>) {}
48194821 431..433 '{}': ()
48204822 447..450 'baz': impl Baz<Assoc = impl Foo>
48214823 480..482 '{}': ()
4822 500..503 'baz': impl Baz<Assoc = &'a impl Foo + 'a>
4824 500..503 'baz': impl Baz<Assoc = &'a (impl Foo + 'a)>
48234825 544..546 '{}': ()
48244826 560..563 'baz': impl Baz<Assoc = Qux<impl Foo>>
48254827 598..600 '{}': ()
src/tools/rust-analyzer/crates/hir-ty/src/utils.rs+8-17
......@@ -22,6 +22,7 @@ use crate::{
2222 TargetFeatures,
2323 db::HirDatabase,
2424 layout::{Layout, TagEncoding},
25 lower::all_supertraits_trait_refs,
2526 mir::pad16,
2627};
2728
......@@ -62,23 +63,13 @@ pub fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[T
6263
6364/// Returns an iterator over the whole super trait hierarchy (including the
6465/// trait itself).
65pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
66 // we need to take care a bit here to avoid infinite loops in case of cycles
67 // (i.e. if we have `trait A: B; trait B: A;`)
68
69 let mut result = smallvec![trait_];
70 let mut i = 0;
71 while let Some(&t) = result.get(i) {
72 // yeah this is quadratic, but trait hierarchies should be flat
73 // enough that this doesn't matter
74 direct_super_traits_cb(db, t, |tt| {
75 if !result.contains(&tt) {
76 result.push(tt);
77 }
78 });
79 i += 1;
80 }
81 result
66pub fn all_super_traits(db: &dyn HirDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
67 let mut supertraits = all_supertraits_trait_refs(db, trait_)
68 .map(|trait_ref| trait_ref.skip_binder().def_id.0)
69 .collect::<SmallVec<[_; _]>>();
70 supertraits.sort_unstable();
71 supertraits.dedup();
72 supertraits
8273}
8374
8475fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
src/tools/rust-analyzer/crates/hir/src/display.rs+2
......@@ -587,6 +587,7 @@ impl<'db> HirDisplay<'db> for TypeParam {
587587 Either::Left(ty),
588588 &predicates,
589589 SizedByDefault::Sized { anchor: krate },
590 false,
590591 );
591592 }
592593 },
......@@ -614,6 +615,7 @@ impl<'db> HirDisplay<'db> for TypeParam {
614615 Either::Left(ty),
615616 &predicates,
616617 default_sized,
618 false,
617619 )?;
618620 }
619621 Ok(())
src/tools/rust-analyzer/crates/hir/src/lib.rs+4
......@@ -4233,6 +4233,10 @@ impl Local {
42334233 self.parent(db).module(db)
42344234 }
42354235
4236 pub fn as_id(self) -> u32 {
4237 self.binding_id.into_raw().into_u32()
4238 }
4239
42364240 pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
42374241 let def = self.parent;
42384242 let infer = InferenceResult::for_body(db, def);
src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs+15-4
......@@ -18,7 +18,6 @@ use hir_ty::{
1818use itertools::Itertools;
1919use rustc_hash::FxHashSet;
2020use rustc_type_ir::inherent::Ty as _;
21use span::Edition;
2221
2322use crate::{
2423 Adt, AssocItem, GenericDef, GenericParam, HasAttrs, HasVisibility, Impl, ModuleDef, ScopeDef,
......@@ -367,7 +366,11 @@ pub(super) fn free_function<'a, 'lt, 'db, DB: HirDatabase>(
367366 let ret_ty = it.ret_type_with_args(db, generics.iter().cloned());
368367 // Filter out private and unsafe functions
369368 if !it.is_visible_from(db, module)
370 || it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
369 || it.is_unsafe_to_call(
370 db,
371 None,
372 crate::Crate::from(ctx.scope.resolver().krate()).edition(db),
373 )
371374 || it.is_unstable(db)
372375 || ctx.config.enable_borrowcheck && ret_ty.contains_reference(db)
373376 || ret_ty.is_raw_ptr()
......@@ -473,7 +476,11 @@ pub(super) fn impl_method<'a, 'lt, 'db, DB: HirDatabase>(
473476
474477 // Filter out private and unsafe functions
475478 if !it.is_visible_from(db, module)
476 || it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
479 || it.is_unsafe_to_call(
480 db,
481 None,
482 crate::Crate::from(ctx.scope.resolver().krate()).edition(db),
483 )
477484 || it.is_unstable(db)
478485 {
479486 return None;
......@@ -667,7 +674,11 @@ pub(super) fn impl_static_method<'a, 'lt, 'db, DB: HirDatabase>(
667674
668675 // Filter out private and unsafe functions
669676 if !it.is_visible_from(db, module)
670 || it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
677 || it.is_unsafe_to_call(
678 db,
679 None,
680 crate::Crate::from(ctx.scope.resolver().krate()).edition(db),
681 )
671682 || it.is_unstable(db)
672683 {
673684 return None;
src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs+1
......@@ -155,6 +155,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
155155 &scope,
156156 mod_path_to_ast(&import_path, edition),
157157 &ctx.config.insert_use,
158 edition,
158159 );
159160 },
160161 );
src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs+1-1
......@@ -132,7 +132,7 @@ pub(crate) fn convert_closure_to_fn(acc: &mut Assists, ctx: &AssistContext<'_>)
132132 );
133133 }
134134
135 if block.try_token().is_none()
135 if block.try_block_modifier().is_none()
136136 && block.unsafe_token().is_none()
137137 && block.label().is_none()
138138 && block.const_token().is_none()
src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs+1-1
......@@ -859,7 +859,7 @@ impl FunctionBody {
859859 ast::BlockExpr(block_expr) => {
860860 let (constness, block) = match block_expr.modifier() {
861861 Some(ast::BlockModifier::Const(_)) => (true, block_expr),
862 Some(ast::BlockModifier::Try(_)) => (false, block_expr),
862 Some(ast::BlockModifier::Try { .. }) => (false, block_expr),
863863 Some(ast::BlockModifier::Label(label)) if label.lifetime().is_some() => (false, block_expr),
864864 _ => continue,
865865 };
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs+23-8
......@@ -1147,14 +1147,7 @@ fn fn_arg_type(
11471147 if ty.is_reference() || ty.is_mutable_reference() {
11481148 let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate());
11491149 convert_reference_type(ty.strip_references(), ctx.db(), famous_defs)
1150 .map(|conversion| {
1151 conversion
1152 .convert_type(
1153 ctx.db(),
1154 target_module.krate(ctx.db()).to_display_target(ctx.db()),
1155 )
1156 .to_string()
1157 })
1150 .map(|conversion| conversion.convert_type(ctx.db(), target_module).to_string())
11581151 .or_else(|| ty.display_source_code(ctx.db(), target_module.into(), true).ok())
11591152 } else {
11601153 ty.display_source_code(ctx.db(), target_module.into(), true).ok()
......@@ -3187,6 +3180,28 @@ fn main() {
31873180 r#"
31883181fn main() {
31893182 s.self$0();
3183}
3184 "#,
3185 );
3186 }
3187
3188 #[test]
3189 fn regression_21288() {
3190 check_assist(
3191 generate_function,
3192 r#"
3193//- minicore: copy
3194fn foo() {
3195 $0bar(&|x| true)
3196}
3197 "#,
3198 r#"
3199fn foo() {
3200 bar(&|x| true)
3201}
3202
3203fn bar(arg: impl Fn(_) -> bool) {
3204 ${0:todo!()}
31903205}
31913206 "#,
31923207 );
src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs+3-3
......@@ -226,15 +226,15 @@ fn generate_getter_from_info(
226226 )
227227 } else {
228228 (|| {
229 let krate = ctx.sema.scope(record_field_info.field_ty.syntax())?.krate();
230 let famous_defs = &FamousDefs(&ctx.sema, krate);
229 let module = ctx.sema.scope(record_field_info.field_ty.syntax())?.module();
230 let famous_defs = &FamousDefs(&ctx.sema, module.krate(ctx.db()));
231231 ctx.sema
232232 .resolve_type(&record_field_info.field_ty)
233233 .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs))
234234 .map(|conversion| {
235235 cov_mark::hit!(convert_reference_type);
236236 (
237 conversion.convert_type(ctx.db(), krate.to_display_target(ctx.db())),
237 conversion.convert_type(ctx.db(), module),
238238 conversion.getter(record_field_info.field_name.to_string()),
239239 )
240240 })
src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs+154-9
......@@ -1,6 +1,7 @@
1use itertools::Itertools;
1use itertools::{Itertools, chain};
22use syntax::{
33 SyntaxKind::WHITESPACE,
4 TextRange,
45 ast::{
56 AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit, make,
67 prec::ExprPrecedence, syntax_factory::SyntaxFactory,
......@@ -44,13 +45,26 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>)
4445 cov_mark::hit!(move_guard_inapplicable_in_arm_body);
4546 return None;
4647 }
47 let space_before_guard = guard.syntax().prev_sibling_or_token();
48 let rest_arms = rest_arms(&match_arm, ctx.selection_trimmed())?;
49 let space_before_delete = chain(
50 guard.syntax().prev_sibling_or_token(),
51 rest_arms.iter().filter_map(|it| it.syntax().prev_sibling_or_token()),
52 );
4853 let space_after_arrow = match_arm.fat_arrow_token()?.next_sibling_or_token();
4954
50 let guard_condition = guard.condition()?.reset_indent();
5155 let arm_expr = match_arm.expr()?;
52 let then_branch = crate::utils::wrap_block(&arm_expr);
53 let if_expr = make::expr_if(guard_condition, then_branch, None).indent(arm_expr.indent_level());
56 let if_branch = chain([&match_arm], &rest_arms)
57 .rfold(None, |else_branch, arm| {
58 if let Some(guard) = arm.guard() {
59 let then_branch = crate::utils::wrap_block(&arm.expr()?);
60 let guard_condition = guard.condition()?.reset_indent();
61 Some(make::expr_if(guard_condition, then_branch, else_branch).into())
62 } else {
63 arm.expr().map(|it| crate::utils::wrap_block(&it).into())
64 }
65 })?
66 .indent(arm_expr.indent_level());
67 let ElseBranch::IfExpr(if_expr) = if_branch else { return None };
5468
5569 let target = guard.syntax().text_range();
5670 acc.add(
......@@ -59,10 +73,13 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>)
5973 target,
6074 |builder| {
6175 let mut edit = builder.make_editor(match_arm.syntax());
62 if let Some(element) = space_before_guard
63 && element.kind() == WHITESPACE
64 {
65 edit.delete(element);
76 for element in space_before_delete {
77 if element.kind() == WHITESPACE {
78 edit.delete(element);
79 }
80 }
81 for rest_arm in &rest_arms {
82 edit.delete(rest_arm.syntax());
6683 }
6784 if let Some(element) = space_after_arrow
6885 && element.kind() == WHITESPACE
......@@ -221,6 +238,25 @@ pub(crate) fn move_arm_cond_to_match_guard(
221238 )
222239}
223240
241fn rest_arms(match_arm: &MatchArm, selection: TextRange) -> Option<Vec<MatchArm>> {
242 match_arm
243 .parent_match()
244 .match_arm_list()?
245 .arms()
246 .skip_while(|it| it != match_arm)
247 .skip(1)
248 .take_while(move |it| {
249 selection.is_empty() || crate::utils::is_selected(it, selection, false)
250 })
251 .take_while(move |it| {
252 it.pat()
253 .zip(match_arm.pat())
254 .is_some_and(|(a, b)| a.syntax().text() == b.syntax().text())
255 })
256 .collect::<Vec<_>>()
257 .into()
258}
259
224260// Parses an if-else-if chain to get the conditions and the then branches until we encounter an else
225261// branch or the end.
226262fn parse_if_chain(if_expr: IfExpr) -> Option<(Vec<(Expr, BlockExpr)>, Option<BlockExpr>)> {
......@@ -344,6 +380,115 @@ fn main() {
344380 );
345381 }
346382
383 #[test]
384 fn move_multiple_guard_to_arm_body_works() {
385 check_assist(
386 move_guard_to_arm_body,
387 r#"
388fn main() {
389 match 92 {
390 x @ 0..30 $0if x % 3 == 0 => false,
391 x @ 0..30 if x % 2 == 0 => true,
392 _ => false
393 }
394}
395"#,
396 r#"
397fn main() {
398 match 92 {
399 x @ 0..30 => if x % 3 == 0 {
400 false
401 } else if x % 2 == 0 {
402 true
403 },
404 _ => false
405 }
406}
407"#,
408 );
409
410 check_assist(
411 move_guard_to_arm_body,
412 r#"
413fn main() {
414 match 92 {
415 x @ 0..30 $0if x % 3 == 0 => false,
416 x @ 0..30 if x % 2 == 0 => true,
417 x @ 0..30 => false,
418 _ => true
419 }
420}
421"#,
422 r#"
423fn main() {
424 match 92 {
425 x @ 0..30 => if x % 3 == 0 {
426 false
427 } else if x % 2 == 0 {
428 true
429 } else {
430 false
431 },
432 _ => true
433 }
434}
435"#,
436 );
437
438 check_assist(
439 move_guard_to_arm_body,
440 r#"
441fn main() {
442 match 92 {
443 x @ 0..30 if x % 3 == 0 => false,
444 x @ 0..30 $0if x % 2 == 0$0 => true,
445 x @ 0..30 => false,
446 _ => true
447 }
448}
449"#,
450 r#"
451fn main() {
452 match 92 {
453 x @ 0..30 if x % 3 == 0 => false,
454 x @ 0..30 => if x % 2 == 0 {
455 true
456 },
457 x @ 0..30 => false,
458 _ => true
459 }
460}
461"#,
462 );
463
464 check_assist(
465 move_guard_to_arm_body,
466 r#"
467fn main() {
468 match 92 {
469 x @ 0..30 $0if x % 3 == 0 => false,
470 x @ 0..30 $0if x % 2 == 0 => true,
471 x @ 0..30 => false,
472 _ => true
473 }
474}
475"#,
476 r#"
477fn main() {
478 match 92 {
479 x @ 0..30 => if x % 3 == 0 {
480 false
481 } else if x % 2 == 0 {
482 true
483 },
484 x @ 0..30 => false,
485 _ => true
486 }
487}
488"#,
489 );
490 }
491
347492 #[test]
348493 fn move_guard_to_block_arm_body_works() {
349494 check_assist(
src/tools/rust-analyzer/crates/ide-assists/src/utils.rs+22-18
......@@ -4,8 +4,7 @@ use std::slice;
44
55pub(crate) use gen_trait_fn_body::gen_trait_fn_body;
66use hir::{
7 DisplayTarget, HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution,
8 Semantics,
7 HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, Semantics,
98 db::{ExpandDatabase, HirDatabase},
109};
1110use ide_db::{
......@@ -836,13 +835,12 @@ enum ReferenceConversionType {
836835}
837836
838837impl<'db> ReferenceConversion<'db> {
839 pub(crate) fn convert_type(
840 &self,
841 db: &'db dyn HirDatabase,
842 display_target: DisplayTarget,
843 ) -> ast::Type {
838 pub(crate) fn convert_type(&self, db: &'db dyn HirDatabase, module: hir::Module) -> ast::Type {
844839 let ty = match self.conversion {
845 ReferenceConversionType::Copy => self.ty.display(db, display_target).to_string(),
840 ReferenceConversionType::Copy => self
841 .ty
842 .display_source_code(db, module.into(), true)
843 .unwrap_or_else(|_| "_".to_owned()),
846844 ReferenceConversionType::AsRefStr => "&str".to_owned(),
847845 ReferenceConversionType::AsRefSlice => {
848846 let type_argument_name = self
......@@ -850,8 +848,8 @@ impl<'db> ReferenceConversion<'db> {
850848 .type_arguments()
851849 .next()
852850 .unwrap()
853 .display(db, display_target)
854 .to_string();
851 .display_source_code(db, module.into(), true)
852 .unwrap_or_else(|_| "_".to_owned());
855853 format!("&[{type_argument_name}]")
856854 }
857855 ReferenceConversionType::Dereferenced => {
......@@ -860,8 +858,8 @@ impl<'db> ReferenceConversion<'db> {
860858 .type_arguments()
861859 .next()
862860 .unwrap()
863 .display(db, display_target)
864 .to_string();
861 .display_source_code(db, module.into(), true)
862 .unwrap_or_else(|_| "_".to_owned());
865863 format!("&{type_argument_name}")
866864 }
867865 ReferenceConversionType::Option => {
......@@ -870,16 +868,22 @@ impl<'db> ReferenceConversion<'db> {
870868 .type_arguments()
871869 .next()
872870 .unwrap()
873 .display(db, display_target)
874 .to_string();
871 .display_source_code(db, module.into(), true)
872 .unwrap_or_else(|_| "_".to_owned());
875873 format!("Option<&{type_argument_name}>")
876874 }
877875 ReferenceConversionType::Result => {
878876 let mut type_arguments = self.ty.type_arguments();
879 let first_type_argument_name =
880 type_arguments.next().unwrap().display(db, display_target).to_string();
881 let second_type_argument_name =
882 type_arguments.next().unwrap().display(db, display_target).to_string();
877 let first_type_argument_name = type_arguments
878 .next()
879 .unwrap()
880 .display_source_code(db, module.into(), true)
881 .unwrap_or_else(|_| "_".to_owned());
882 let second_type_argument_name = type_arguments
883 .next()
884 .unwrap()
885 .display_source_code(db, module.into(), true)
886 .unwrap_or_else(|_| "_".to_owned());
883887 format!("Result<&{first_type_argument_name}, &{second_type_argument_name}>")
884888 }
885889 };
src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs+52-1
......@@ -151,6 +151,10 @@ pub(crate) fn complete_postfix(
151151 .add_to(acc, ctx.db);
152152 }
153153 },
154 _ if is_in_cond => {
155 postfix_snippet("let", "let", &format!("let $1 = {receiver_text}"))
156 .add_to(acc, ctx.db);
157 }
154158 _ if matches!(second_ancestor.kind(), STMT_LIST | EXPR_STMT) => {
155159 postfix_snippet("let", "let", &format!("let $0 = {receiver_text};"))
156160 .add_to(acc, ctx.db);
......@@ -253,7 +257,6 @@ pub(crate) fn complete_postfix(
253257 &format!("while {receiver_text} {{\n $0\n}}"),
254258 )
255259 .add_to(acc, ctx.db);
256 postfix_snippet("not", "!expr", &format!("!{receiver_text}")).add_to(acc, ctx.db);
257260 } else if let Some(trait_) = ctx.famous_defs().core_iter_IntoIterator()
258261 && receiver_ty.impls_trait(ctx.db, trait_, &[])
259262 {
......@@ -266,6 +269,10 @@ pub(crate) fn complete_postfix(
266269 }
267270 }
268271
272 if receiver_ty.is_bool() || receiver_ty.is_unknown() {
273 postfix_snippet("not", "!expr", &format!("!{receiver_text}")).add_to(acc, ctx.db);
274 }
275
269276 let block_should_be_wrapped = if let ast::Expr::BlockExpr(block) = dot_receiver {
270277 block.modifier().is_some() || !block.is_standalone()
271278 } else {
......@@ -585,6 +592,31 @@ fn main() {
585592 );
586593 }
587594
595 #[test]
596 fn postfix_completion_works_in_if_condition() {
597 check(
598 r#"
599fn foo(cond: bool) {
600 if cond.$0
601}
602"#,
603 expect![[r#"
604 sn box Box::new(expr)
605 sn call function(expr)
606 sn const const {}
607 sn dbg dbg!(expr)
608 sn dbgr dbg!(&expr)
609 sn deref *expr
610 sn let let
611 sn not !expr
612 sn ref &expr
613 sn refm &mut expr
614 sn return return expr
615 sn unsafe unsafe {}
616 "#]],
617 );
618 }
619
588620 #[test]
589621 fn postfix_type_filtering() {
590622 check(
......@@ -744,6 +776,25 @@ fn main() {
744776 );
745777 }
746778
779 #[test]
780 fn iflet_fallback_cond() {
781 check_edit(
782 "let",
783 r#"
784fn main() {
785 let bar = 2;
786 if bar.$0
787}
788"#,
789 r#"
790fn main() {
791 let bar = 2;
792 if let $1 = bar
793}
794"#,
795 );
796 }
797
747798 #[test]
748799 fn option_letelse() {
749800 check_edit(
src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs+7-2
......@@ -146,9 +146,14 @@ pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) {
146146 insert_use_with_alias_option(scope, path, cfg, None);
147147}
148148
149pub fn insert_use_as_alias(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) {
149pub fn insert_use_as_alias(
150 scope: &ImportScope,
151 path: ast::Path,
152 cfg: &InsertUseConfig,
153 edition: span::Edition,
154) {
150155 let text: &str = "use foo as _";
151 let parse = syntax::SourceFile::parse(text, span::Edition::CURRENT_FIXME);
156 let parse = syntax::SourceFile::parse(text, edition);
152157 let node = parse
153158 .tree()
154159 .syntax()
src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs+3-3
......@@ -49,7 +49,7 @@ pub fn is_closure_or_blk_with_modif(expr: &ast::Expr) -> bool {
4949 block_expr.modifier(),
5050 Some(
5151 ast::BlockModifier::Async(_)
52 | ast::BlockModifier::Try(_)
52 | ast::BlockModifier::Try { .. }
5353 | ast::BlockModifier::Const(_)
5454 )
5555 )
......@@ -148,7 +148,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) {
148148 block_expr.modifier(),
149149 Some(
150150 ast::BlockModifier::Async(_)
151 | ast::BlockModifier::Try(_)
151 | ast::BlockModifier::Try { .. }
152152 | ast::BlockModifier::Const(_)
153153 )
154154 )
......@@ -291,7 +291,7 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
291291 match b.modifier() {
292292 Some(
293293 ast::BlockModifier::Async(_)
294 | ast::BlockModifier::Try(_)
294 | ast::BlockModifier::Try { .. }
295295 | ast::BlockModifier::Const(_),
296296 ) => return cb(expr),
297297
src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs+29-21
......@@ -206,17 +206,18 @@ impl NameGenerator {
206206 expr: &ast::Expr,
207207 sema: &Semantics<'_, RootDatabase>,
208208 ) -> Option<SmolStr> {
209 let edition = sema.scope(expr.syntax())?.krate().edition(sema.db);
209210 // `from_param` does not benefit from stripping it need the largest
210211 // context possible so we check firstmost
211 if let Some(name) = from_param(expr, sema) {
212 if let Some(name) = from_param(expr, sema, edition) {
212213 return Some(self.suggest_name(&name));
213214 }
214215
215216 let mut next_expr = Some(expr.clone());
216217 while let Some(expr) = next_expr {
217 let name = from_call(&expr)
218 .or_else(|| from_type(&expr, sema))
219 .or_else(|| from_field_name(&expr));
218 let name = from_call(&expr, edition)
219 .or_else(|| from_type(&expr, sema, edition))
220 .or_else(|| from_field_name(&expr, edition));
220221 if let Some(name) = name {
221222 return Some(self.suggest_name(&name));
222223 }
......@@ -270,7 +271,7 @@ impl NameGenerator {
270271 }
271272}
272273
273fn normalize(name: &str) -> Option<SmolStr> {
274fn normalize(name: &str, edition: syntax::Edition) -> Option<SmolStr> {
274275 let name = to_lower_snake_case(name).to_smolstr();
275276
276277 if USELESS_NAMES.contains(&name.as_str()) {
......@@ -281,16 +282,16 @@ fn normalize(name: &str) -> Option<SmolStr> {
281282 return None;
282283 }
283284
284 if !is_valid_name(&name) {
285 if !is_valid_name(&name, edition) {
285286 return None;
286287 }
287288
288289 Some(name)
289290}
290291
291fn is_valid_name(name: &str) -> bool {
292fn is_valid_name(name: &str, edition: syntax::Edition) -> bool {
292293 matches!(
293 super::LexedStr::single_token(syntax::Edition::CURRENT_FIXME, name),
294 super::LexedStr::single_token(edition, name),
294295 Some((syntax::SyntaxKind::IDENT, _error))
295296 )
296297}
......@@ -304,11 +305,11 @@ fn is_useless_method(method: &ast::MethodCallExpr) -> bool {
304305 }
305306}
306307
307fn from_call(expr: &ast::Expr) -> Option<SmolStr> {
308 from_func_call(expr).or_else(|| from_method_call(expr))
308fn from_call(expr: &ast::Expr, edition: syntax::Edition) -> Option<SmolStr> {
309 from_func_call(expr, edition).or_else(|| from_method_call(expr, edition))
309310}
310311
311fn from_func_call(expr: &ast::Expr) -> Option<SmolStr> {
312fn from_func_call(expr: &ast::Expr, edition: syntax::Edition) -> Option<SmolStr> {
312313 let call = match expr {
313314 ast::Expr::CallExpr(call) => call,
314315 _ => return None,
......@@ -318,10 +319,10 @@ fn from_func_call(expr: &ast::Expr) -> Option<SmolStr> {
318319 _ => return None,
319320 };
320321 let ident = func.path()?.segment()?.name_ref()?.ident_token()?;
321 normalize(ident.text())
322 normalize(ident.text(), edition)
322323}
323324
324fn from_method_call(expr: &ast::Expr) -> Option<SmolStr> {
325fn from_method_call(expr: &ast::Expr, edition: syntax::Edition) -> Option<SmolStr> {
325326 let method = match expr {
326327 ast::Expr::MethodCallExpr(call) => call,
327328 _ => return None,
......@@ -340,10 +341,14 @@ fn from_method_call(expr: &ast::Expr) -> Option<SmolStr> {
340341 }
341342 }
342343
343 normalize(name)
344 normalize(name, edition)
344345}
345346
346fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<SmolStr> {
347fn from_param(
348 expr: &ast::Expr,
349 sema: &Semantics<'_, RootDatabase>,
350 edition: Edition,
351) -> Option<SmolStr> {
347352 let arg_list = expr.syntax().parent().and_then(ast::ArgList::cast)?;
348353 let args_parent = arg_list.syntax().parent()?;
349354 let func = match_ast! {
......@@ -362,7 +367,7 @@ fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<Sm
362367 let param = func.params().into_iter().nth(idx)?;
363368 let pat = sema.source(param)?.value.right()?.pat()?;
364369 let name = var_name_from_pat(&pat)?;
365 normalize(&name.to_smolstr())
370 normalize(&name.to_smolstr(), edition)
366371}
367372
368373fn var_name_from_pat(pat: &ast::Pat) -> Option<ast::Name> {
......@@ -374,10 +379,13 @@ fn var_name_from_pat(pat: &ast::Pat) -> Option<ast::Name> {
374379 }
375380}
376381
377fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<SmolStr> {
382fn from_type(
383 expr: &ast::Expr,
384 sema: &Semantics<'_, RootDatabase>,
385 edition: Edition,
386) -> Option<SmolStr> {
378387 let ty = sema.type_of_expr(expr)?.adjusted();
379388 let ty = ty.remove_ref().unwrap_or(ty);
380 let edition = sema.scope(expr.syntax())?.krate().edition(sema.db);
381389
382390 name_of_type(&ty, sema.db, edition)
383391}
......@@ -417,7 +425,7 @@ fn name_of_type<'db>(
417425 } else {
418426 return None;
419427 };
420 normalize(&name)
428 normalize(&name, edition)
421429}
422430
423431fn sequence_name<'db>(
......@@ -450,13 +458,13 @@ fn trait_name(trait_: &hir::Trait, db: &RootDatabase, edition: Edition) -> Optio
450458 Some(name)
451459}
452460
453fn from_field_name(expr: &ast::Expr) -> Option<SmolStr> {
461fn from_field_name(expr: &ast::Expr, edition: syntax::Edition) -> Option<SmolStr> {
454462 let field = match expr {
455463 ast::Expr::FieldExpr(field) => field,
456464 _ => return None,
457465 };
458466 let ident = field.name_ref()?.ident_token()?;
459 normalize(ident.text())
467 normalize(ident.text(), edition)
460468}
461469
462470#[cfg(test)]
src/tools/rust-analyzer/crates/ide/src/goto_definition.rs+3-3
......@@ -332,7 +332,7 @@ pub(crate) fn find_fn_or_blocks(
332332 ast::BlockExpr(blk) => {
333333 match blk.modifier() {
334334 Some(ast::BlockModifier::Async(_)) => blk.syntax().clone(),
335 Some(ast::BlockModifier::Try(_)) if token_kind != T![return] => blk.syntax().clone(),
335 Some(ast::BlockModifier::Try { .. }) if token_kind != T![return] => blk.syntax().clone(),
336336 _ => continue,
337337 }
338338 },
......@@ -404,8 +404,8 @@ fn nav_for_exit_points(
404404 let blk_in_file = InFile::new(file_id, blk.into());
405405 Some(expr_to_nav(db, blk_in_file, Some(async_tok)))
406406 },
407 Some(ast::BlockModifier::Try(_)) if token_kind != T![return] => {
408 let try_tok = blk.try_token()?.text_range();
407 Some(ast::BlockModifier::Try { .. }) if token_kind != T![return] => {
408 let try_tok = blk.try_block_modifier()?.try_token()?.text_range();
409409 let blk_in_file = InFile::new(file_id, blk.into());
410410 Some(expr_to_nav(db, blk_in_file, Some(try_tok)))
411411 },
src/tools/rust-analyzer/crates/ide/src/highlight_related.rs+1-1
......@@ -473,7 +473,7 @@ pub(crate) fn highlight_exit_points(
473473 },
474474 ast::BlockExpr(blk) => match blk.modifier() {
475475 Some(ast::BlockModifier::Async(t)) => hl_exit_points(sema, Some(t), blk.into()),
476 Some(ast::BlockModifier::Try(t)) if token.kind() != T![return] => {
476 Some(ast::BlockModifier::Try { try_token: t, .. }) if token.kind() != T![return] => {
477477 hl_exit_points(sema, Some(t), blk.into())
478478 },
479479 _ => continue,
src/tools/rust-analyzer/crates/ide/src/hover/render.rs+1-1
......@@ -74,7 +74,7 @@ pub(super) fn try_expr(
7474 ast::Fn(fn_) => sema.to_def(&fn_)?.ret_type(sema.db),
7575 ast::Item(__) => return None,
7676 ast::ClosureExpr(closure) => sema.type_of_expr(&closure.body()?)?.original,
77 ast::BlockExpr(block_expr) => if matches!(block_expr.modifier(), Some(ast::BlockModifier::Async(_) | ast::BlockModifier::Try(_)| ast::BlockModifier::Const(_))) {
77 ast::BlockExpr(block_expr) => if matches!(block_expr.modifier(), Some(ast::BlockModifier::Async(_) | ast::BlockModifier::Try { .. } | ast::BlockModifier::Const(_))) {
7878 sema.type_of_expr(&block_expr.into())?.original
7979 } else {
8080 continue;
src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs+17
......@@ -1382,4 +1382,21 @@ fn f<'a>() {
13821382 "#]],
13831383 );
13841384 }
1385
1386 #[test]
1387 fn ref_multi_trait_impl_trait() {
1388 check_with_config(
1389 InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG },
1390 r#"
1391//- minicore: sized
1392trait Eq {}
1393trait Ord {}
1394
1395fn foo(argument: &(impl Eq + Ord)) {
1396 let x = argument;
1397 // ^ &(impl Eq + Ord)
1398}
1399 "#,
1400 );
1401 }
13851402}
src/tools/rust-analyzer/crates/ide/src/lib.rs+5-1
......@@ -67,7 +67,7 @@ use ide_db::{
6767 FxHashMap, FxIndexSet, LineIndexDatabase,
6868 base_db::{
6969 CrateOrigin, CrateWorkspaceData, Env, FileSet, RootQueryDb, SourceDatabase, VfsPath,
70 salsa::{Cancelled, Database},
70 salsa::{CancellationToken, Cancelled, Database},
7171 },
7272 prime_caches, symbol_index,
7373};
......@@ -947,6 +947,10 @@ impl Analysis {
947947 // We use `attach_db_allow_change()` and not `attach_db()` because fixture injection can change the database.
948948 hir::attach_db_allow_change(&self.db, || Cancelled::catch(|| f(&self.db)))
949949 }
950
951 pub fn cancellation_token(&self) -> CancellationToken {
952 self.db.cancellation_token()
953 }
950954}
951955
952956#[test]
src/tools/rust-analyzer/crates/ide/src/signature_help.rs+2-2
......@@ -1975,8 +1975,8 @@ trait Sub: Super + Super {
19751975fn f() -> impl Sub<$0
19761976 "#,
19771977 expect![[r#"
1978 trait Sub<SubTy = …, SuperTy = …>
1979 ^^^^^^^^^ -----------
1978 trait Sub<SuperTy = …, SubTy = …>
1979 ^^^^^^^^^^^ ---------
19801980 "#]],
19811981 );
19821982 }
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs+7-12
......@@ -14,7 +14,7 @@ mod tests;
1414use std::ops::ControlFlow;
1515
1616use either::Either;
17use hir::{DefWithBody, EditionedFileId, InFile, InRealFile, MacroKind, Name, Semantics};
17use hir::{DefWithBody, EditionedFileId, InFile, InRealFile, MacroKind, Semantics};
1818use ide_db::{FxHashMap, FxHashSet, MiniCore, Ranker, RootDatabase, SymbolKind};
1919use syntax::{
2020 AstNode, AstToken, NodeOrToken,
......@@ -257,8 +257,7 @@ fn traverse(
257257
258258 // FIXME: accommodate range highlighting
259259 let mut body_stack: Vec<Option<DefWithBody>> = vec![];
260 let mut per_body_cache: FxHashMap<DefWithBody, (FxHashSet<_>, FxHashMap<Name, u32>)> =
261 FxHashMap::default();
260 let mut per_body_cache: FxHashMap<DefWithBody, FxHashSet<_>> = FxHashMap::default();
262261
263262 // Walk all nodes, keeping track of whether we are inside a macro or not.
264263 // If in macro, expand it first and highlight the expanded code.
......@@ -422,14 +421,11 @@ fn traverse(
422421 }
423422
424423 let edition = descended_element.file_id.edition(sema.db);
425 let (unsafe_ops, bindings_shadow_count) = match current_body {
426 Some(current_body) => {
427 let (ops, bindings) = per_body_cache
428 .entry(current_body)
429 .or_insert_with(|| (sema.get_unsafe_ops(current_body), Default::default()));
430 (&*ops, Some(bindings))
431 }
432 None => (&empty, None),
424 let unsafe_ops = match current_body {
425 Some(current_body) => per_body_cache
426 .entry(current_body)
427 .or_insert_with(|| sema.get_unsafe_ops(current_body)),
428 None => &empty,
433429 };
434430 let is_unsafe_node =
435431 |node| unsafe_ops.contains(&InFile::new(descended_element.file_id, node));
......@@ -438,7 +434,6 @@ fn traverse(
438434 let hl = highlight::name_like(
439435 sema,
440436 krate,
441 bindings_shadow_count,
442437 &is_unsafe_node,
443438 config.syntactic_name_ref_highlighting,
444439 name_like,
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs+8-32
......@@ -5,12 +5,11 @@ use std::ops::ControlFlow;
55use either::Either;
66use hir::{AsAssocItem, HasAttrs, HasVisibility, Semantics};
77use ide_db::{
8 FxHashMap, RootDatabase, SymbolKind,
8 RootDatabase, SymbolKind,
99 defs::{Definition, IdentClass, NameClass, NameRefClass},
1010 syntax_helpers::node_ext::walk_pat,
1111};
1212use span::Edition;
13use stdx::hash_once;
1413use syntax::{
1514 AstNode, AstPtr, AstToken, NodeOrToken,
1615 SyntaxKind::{self, *},
......@@ -64,7 +63,6 @@ pub(super) fn token(
6463pub(super) fn name_like(
6564 sema: &Semantics<'_, RootDatabase>,
6665 krate: Option<hir::Crate>,
67 bindings_shadow_count: Option<&mut FxHashMap<hir::Name, u32>>,
6866 is_unsafe_node: &impl Fn(AstPtr<Either<ast::Expr, ast::Pat>>) -> bool,
6967 syntactic_name_ref_highlighting: bool,
7068 name_like: ast::NameLike,
......@@ -75,22 +73,15 @@ pub(super) fn name_like(
7573 ast::NameLike::NameRef(name_ref) => highlight_name_ref(
7674 sema,
7775 krate,
78 bindings_shadow_count,
7976 &mut binding_hash,
8077 is_unsafe_node,
8178 syntactic_name_ref_highlighting,
8279 name_ref,
8380 edition,
8481 ),
85 ast::NameLike::Name(name) => highlight_name(
86 sema,
87 bindings_shadow_count,
88 &mut binding_hash,
89 is_unsafe_node,
90 krate,
91 name,
92 edition,
93 ),
82 ast::NameLike::Name(name) => {
83 highlight_name(sema, &mut binding_hash, is_unsafe_node, krate, name, edition)
84 }
9485 ast::NameLike::Lifetime(lifetime) => match IdentClass::classify_lifetime(sema, &lifetime) {
9586 Some(IdentClass::NameClass(NameClass::Definition(def))) => {
9687 highlight_def(sema, krate, def, edition, false) | HlMod::Definition
......@@ -273,7 +264,6 @@ fn keyword(token: SyntaxToken, kind: SyntaxKind) -> Highlight {
273264fn highlight_name_ref(
274265 sema: &Semantics<'_, RootDatabase>,
275266 krate: Option<hir::Crate>,
276 bindings_shadow_count: Option<&mut FxHashMap<hir::Name, u32>>,
277267 binding_hash: &mut Option<u64>,
278268 is_unsafe_node: &impl Fn(AstPtr<Either<ast::Expr, ast::Pat>>) -> bool,
279269 syntactic_name_ref_highlighting: bool,
......@@ -306,12 +296,8 @@ fn highlight_name_ref(
306296 };
307297 let mut h = match name_class {
308298 NameRefClass::Definition(def, _) => {
309 if let Definition::Local(local) = &def
310 && let Some(bindings_shadow_count) = bindings_shadow_count
311 {
312 let name = local.name(sema.db);
313 let shadow_count = bindings_shadow_count.entry(name.clone()).or_default();
314 *binding_hash = Some(calc_binding_hash(&name, *shadow_count))
299 if let Definition::Local(local) = &def {
300 *binding_hash = Some(local.as_id() as u64);
315301 };
316302
317303 let mut h = highlight_def(sema, krate, def, edition, true);
......@@ -432,7 +418,6 @@ fn highlight_name_ref(
432418
433419fn highlight_name(
434420 sema: &Semantics<'_, RootDatabase>,
435 bindings_shadow_count: Option<&mut FxHashMap<hir::Name, u32>>,
436421 binding_hash: &mut Option<u64>,
437422 is_unsafe_node: &impl Fn(AstPtr<Either<ast::Expr, ast::Pat>>) -> bool,
438423 krate: Option<hir::Crate>,
......@@ -440,13 +425,8 @@ fn highlight_name(
440425 edition: Edition,
441426) -> Highlight {
442427 let name_kind = NameClass::classify(sema, &name);
443 if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind
444 && let Some(bindings_shadow_count) = bindings_shadow_count
445 {
446 let name = local.name(sema.db);
447 let shadow_count = bindings_shadow_count.entry(name.clone()).or_default();
448 *shadow_count += 1;
449 *binding_hash = Some(calc_binding_hash(&name, *shadow_count))
428 if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind {
429 *binding_hash = Some(local.as_id() as u64);
450430 };
451431 match name_kind {
452432 Some(NameClass::Definition(def)) => {
......@@ -474,10 +454,6 @@ fn highlight_name(
474454 }
475455}
476456
477fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 {
478 hash_once::<ide_db::FxHasher>((name.as_str(), shadow_count))
479}
480
481457pub(super) fn highlight_def(
482458 sema: &Semantics<'_, RootDatabase>,
483459 krate: Option<hir::Crate>,
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html+6-6
......@@ -42,14 +42,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
4242.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
4343</style>
4444<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
45 <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="18084384843626695225" style="color: hsl(154,95%,53%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
46 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="5697120079570210533" style="color: hsl(268,86%,80%);">x</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="18084384843626695225" style="color: hsl(154,95%,53%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
47 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="4222724691718692706" style="color: hsl(156,71%,51%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="18084384843626695225" style="color: hsl(154,95%,53%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
45 <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="0" style="color: hsl(74,59%,48%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
46 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="1" style="color: hsl(152,51%,64%);">x</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="0" style="color: hsl(74,59%,48%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
47 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2" style="color: hsl(272,82%,82%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="0" style="color: hsl(74,59%,48%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
4848
49 <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="17855021198829413584" style="color: hsl(230,76%,79%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span>
50 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="16380625810977895757" style="color: hsl(262,75%,75%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="17855021198829413584" style="color: hsl(230,76%,79%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
49 <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="3" style="color: hsl(107,98%,81%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span>
50 <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="4" style="color: hsl(241,93%,64%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="3" style="color: hsl(107,98%,81%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
5151<span class="brace">}</span>
5252
5353<span class="keyword">fn</span> <span class="function declaration">bar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
54 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable reference" data-binding-hash="18084384843626695225" style="color: hsl(154,95%,53%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
54 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable reference" data-binding-hash="0" style="color: hsl(74,59%,48%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
5555<span class="brace">}</span></code></pre>
\ No newline at end of file
src/tools/rust-analyzer/crates/ide/src/typing.rs+11-7
......@@ -17,7 +17,10 @@ mod on_enter;
1717
1818use either::Either;
1919use hir::EditionedFileId;
20use ide_db::{FilePosition, RootDatabase, base_db::RootQueryDb};
20use ide_db::{
21 FilePosition, RootDatabase,
22 base_db::{RootQueryDb, SourceDatabase},
23};
2124use span::Edition;
2225use std::iter;
2326
......@@ -70,11 +73,12 @@ pub(crate) fn on_char_typed(
7073 if !TRIGGER_CHARS.contains(&char_typed) {
7174 return None;
7275 }
73 // FIXME: We need to figure out the edition of the file here, but that means hitting the
74 // database for more than just parsing the file which is bad.
76 let edition = db
77 .source_root_crates(db.file_source_root(position.file_id).source_root_id(db))
78 .first()
79 .map_or(Edition::CURRENT, |crates| crates.data(db).edition);
7580 // FIXME: We are hitting the database here, if we are unlucky this call might block momentarily
76 // causing the editor to feel sluggish!
77 let edition = Edition::CURRENT_FIXME;
81 // causing the editor to feel sluggish! We need to make this bail if it would block too long?
7882 let editioned_file_id_wrapper = EditionedFileId::from_span_guess_origin(
7983 db,
8084 span::EditionedFileId::new(position.file_id, edition),
......@@ -457,8 +461,8 @@ mod tests {
457461 let (offset, mut before) = extract_offset(before);
458462 let edit = TextEdit::insert(offset, char_typed.to_string());
459463 edit.apply(&mut before);
460 let parse = SourceFile::parse(&before, span::Edition::CURRENT_FIXME);
461 on_char_typed_(&parse, offset, char_typed, span::Edition::CURRENT_FIXME).map(|it| {
464 let parse = SourceFile::parse(&before, span::Edition::CURRENT);
465 on_char_typed_(&parse, offset, char_typed, span::Edition::CURRENT).map(|it| {
462466 it.apply(&mut before);
463467 before.to_string()
464468 })
src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs+2
......@@ -110,6 +110,7 @@ define_symbols! {
110110 win64_dash_unwind = "win64-unwind",
111111 x86_dash_interrupt = "x86-interrupt",
112112 rust_dash_preserve_dash_none = "preserve-none",
113 _0_u8 = "0_u8",
113114
114115 @PLAIN:
115116 __ra_fixup,
......@@ -285,6 +286,7 @@ define_symbols! {
285286 Into,
286287 into_future,
287288 into_iter,
289 into_try_type,
288290 IntoFuture,
289291 IntoIter,
290292 IntoIterator,
src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs+6
......@@ -976,11 +976,17 @@ fn break_expr(p: &mut Parser<'_>, r: Restrictions) -> CompletedMarker {
976976// test try_block_expr
977977// fn foo() {
978978// let _ = try {};
979// let _ = try bikeshed T<U> {};
979980// }
980981fn try_block_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
981982 assert!(p.at(T![try]));
982983 let m = m.unwrap_or_else(|| p.start());
984 let try_modifier = p.start();
983985 p.bump(T![try]);
986 if p.eat_contextual_kw(T![bikeshed]) {
987 type_(p);
988 }
989 try_modifier.complete(p, TRY_BLOCK_MODIFIER);
984990 if p.at(T!['{']) {
985991 stmt_list(p);
986992 } else {
src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs+8
......@@ -114,6 +114,7 @@ pub enum SyntaxKind {
114114 ATT_SYNTAX_KW,
115115 AUTO_KW,
116116 AWAIT_KW,
117 BIKESHED_KW,
117118 BUILTIN_KW,
118119 CLOBBER_ABI_KW,
119120 DEFAULT_KW,
......@@ -285,6 +286,7 @@ pub enum SyntaxKind {
285286 STRUCT,
286287 TOKEN_TREE,
287288 TRAIT,
289 TRY_BLOCK_MODIFIER,
288290 TRY_EXPR,
289291 TUPLE_EXPR,
290292 TUPLE_FIELD,
......@@ -458,6 +460,7 @@ impl SyntaxKind {
458460 | STRUCT
459461 | TOKEN_TREE
460462 | TRAIT
463 | TRY_BLOCK_MODIFIER
461464 | TRY_EXPR
462465 | TUPLE_EXPR
463466 | TUPLE_FIELD
......@@ -596,6 +599,7 @@ impl SyntaxKind {
596599 ASM_KW => "asm",
597600 ATT_SYNTAX_KW => "att_syntax",
598601 AUTO_KW => "auto",
602 BIKESHED_KW => "bikeshed",
599603 BUILTIN_KW => "builtin",
600604 CLOBBER_ABI_KW => "clobber_abi",
601605 DEFAULT_KW => "default",
......@@ -698,6 +702,7 @@ impl SyntaxKind {
698702 ASM_KW => true,
699703 ATT_SYNTAX_KW => true,
700704 AUTO_KW => true,
705 BIKESHED_KW => true,
701706 BUILTIN_KW => true,
702707 CLOBBER_ABI_KW => true,
703708 DEFAULT_KW => true,
......@@ -788,6 +793,7 @@ impl SyntaxKind {
788793 ASM_KW => true,
789794 ATT_SYNTAX_KW => true,
790795 AUTO_KW => true,
796 BIKESHED_KW => true,
791797 BUILTIN_KW => true,
792798 CLOBBER_ABI_KW => true,
793799 DEFAULT_KW => true,
......@@ -941,6 +947,7 @@ impl SyntaxKind {
941947 "asm" => ASM_KW,
942948 "att_syntax" => ATT_SYNTAX_KW,
943949 "auto" => AUTO_KW,
950 "bikeshed" => BIKESHED_KW,
944951 "builtin" => BUILTIN_KW,
945952 "clobber_abi" => CLOBBER_ABI_KW,
946953 "default" => DEFAULT_KW,
......@@ -1112,6 +1119,7 @@ macro_rules ! T_ {
11121119 [asm] => { $ crate :: SyntaxKind :: ASM_KW };
11131120 [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW };
11141121 [auto] => { $ crate :: SyntaxKind :: AUTO_KW };
1122 [bikeshed] => { $ crate :: SyntaxKind :: BIKESHED_KW };
11151123 [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW };
11161124 [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW };
11171125 [default] => { $ crate :: SyntaxKind :: DEFAULT_KW };
src/tools/rust-analyzer/crates/parser/test_data/parser/err/0042_weird_blocks.rast+2-1
......@@ -45,7 +45,8 @@ SOURCE_FILE
4545 WHITESPACE " "
4646 EXPR_STMT
4747 BLOCK_EXPR
48 TRY_KW "try"
48 TRY_BLOCK_MODIFIER
49 TRY_KW "try"
4950 WHITESPACE " "
5051 LITERAL
5152 INT_NUMBER "92"
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_block_expr.rast+36-1
......@@ -21,7 +21,42 @@ SOURCE_FILE
2121 EQ "="
2222 WHITESPACE " "
2323 BLOCK_EXPR
24 TRY_KW "try"
24 TRY_BLOCK_MODIFIER
25 TRY_KW "try"
26 WHITESPACE " "
27 STMT_LIST
28 L_CURLY "{"
29 R_CURLY "}"
30 SEMICOLON ";"
31 WHITESPACE "\n "
32 LET_STMT
33 LET_KW "let"
34 WHITESPACE " "
35 WILDCARD_PAT
36 UNDERSCORE "_"
37 WHITESPACE " "
38 EQ "="
39 WHITESPACE " "
40 BLOCK_EXPR
41 TRY_BLOCK_MODIFIER
42 TRY_KW "try"
43 WHITESPACE " "
44 BIKESHED_KW "bikeshed"
45 WHITESPACE " "
46 PATH_TYPE
47 PATH
48 PATH_SEGMENT
49 NAME_REF
50 IDENT "T"
51 GENERIC_ARG_LIST
52 L_ANGLE "<"
53 TYPE_ARG
54 PATH_TYPE
55 PATH
56 PATH_SEGMENT
57 NAME_REF
58 IDENT "U"
59 R_ANGLE ">"
2560 WHITESPACE " "
2661 STMT_LIST
2762 L_CURLY "{"
src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_block_expr.rs+1
......@@ -1,3 +1,4 @@
11fn foo() {
22 let _ = try {};
3 let _ = try bikeshed T<U> {};
34}
src/tools/rust-analyzer/crates/project-model/src/sysroot.rs+5-1
......@@ -275,7 +275,10 @@ impl Sysroot {
275275 }
276276 tracing::debug!("Stitching sysroot library: {src_root}");
277277
278 let mut stitched = stitched::Stitched { crates: Default::default() };
278 let mut stitched = stitched::Stitched {
279 crates: Default::default(),
280 edition: span::Edition::Edition2024,
281 };
279282
280283 for path in stitched::SYSROOT_CRATES.trim().lines() {
281284 let name = path.split('/').next_back().unwrap();
......@@ -511,6 +514,7 @@ pub(crate) mod stitched {
511514 #[derive(Debug, Clone, Eq, PartialEq)]
512515 pub struct Stitched {
513516 pub(super) crates: Arena<RustLibSrcCrateData>,
517 pub(crate) edition: span::Edition,
514518 }
515519
516520 impl ops::Index<RustLibSrcCrate> for Stitched {
src/tools/rust-analyzer/crates/project-model/src/workspace.rs+1-1
......@@ -1831,7 +1831,7 @@ fn sysroot_to_crate_graph(
18311831 let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name);
18321832 let crate_id = crate_graph.add_crate_root(
18331833 file_id,
1834 Edition::CURRENT_FIXME,
1834 stitched.edition,
18351835 Some(display_name),
18361836 None,
18371837 cfg_options.clone(),
src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs+145-143
......@@ -22,7 +22,6 @@ use serde_derive::Deserialize;
2222pub(crate) use cargo_metadata::diagnostic::{
2323 Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan,
2424};
25use toolchain::DISPLAY_COMMAND_IGNORE_ENVS;
2625use toolchain::Tool;
2726use triomphe::Arc;
2827
......@@ -144,6 +143,7 @@ impl FlycheckConfig {
144143}
145144
146145impl fmt::Display for FlycheckConfig {
146 /// Show a shortened version of the check command.
147147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148148 match self {
149149 FlycheckConfig::Automatic { cargo_options, .. } => {
......@@ -153,12 +153,23 @@ impl fmt::Display for FlycheckConfig {
153153 // Don't show `my_custom_check --foo $saved_file` literally to the user, as it
154154 // looks like we've forgotten to substitute $saved_file.
155155 //
156 // `my_custom_check --foo /home/user/project/src/dir/foo.rs` is too verbose.
157 //
156158 // Instead, show `my_custom_check --foo ...`. The
157159 // actual path is often too long to be worth showing
158160 // in the IDE (e.g. in the VS Code status bar).
159161 let display_args = args
160162 .iter()
161 .map(|arg| if arg == SAVED_FILE_PLACEHOLDER_DOLLAR { "..." } else { arg })
163 .map(|arg| {
164 if (arg == SAVED_FILE_PLACEHOLDER_DOLLAR)
165 || (arg == SAVED_FILE_INLINE)
166 || arg.ends_with(".rs")
167 {
168 "..."
169 } else {
170 arg
171 }
172 })
162173 .collect::<Vec<_>>();
163174
164175 write!(f, "{command} {}", display_args.join(" "))
......@@ -403,24 +414,30 @@ struct FlycheckActor {
403414 /// doesn't provide a way to read sub-process output without blocking, so we
404415 /// have to wrap sub-processes output handling in a thread and pass messages
405416 /// back over a channel.
406 command_handle: Option<CommandHandle<CargoCheckMessage>>,
417 command_handle: Option<CommandHandle<CheckMessage>>,
407418 /// The receiver side of the channel mentioned above.
408 command_receiver: Option<Receiver<CargoCheckMessage>>,
419 command_receiver: Option<Receiver<CheckMessage>>,
409420 diagnostics_cleared_for: FxHashSet<PackageSpecifier>,
410421 diagnostics_received: DiagnosticsReceived,
411422}
412423
413#[derive(PartialEq)]
424#[derive(PartialEq, Debug)]
414425enum DiagnosticsReceived {
415 Yes,
416 No,
417 YesAndClearedForAll,
426 /// We started a flycheck, but we haven't seen any diagnostics yet.
427 NotYet,
428 /// We received a non-zero number of diagnostics from rustc or clippy (via
429 /// cargo or custom check command). This means there were errors or
430 /// warnings.
431 AtLeastOne,
432 /// We received a non-zero number of diagnostics, and the scope is
433 /// workspace, so we've discarded the previous workspace diagnostics.
434 AtLeastOneAndClearedWorkspace,
418435}
419436
420437#[allow(clippy::large_enum_variant)]
421438enum Event {
422439 RequestStateChange(StateChange),
423 CheckEvent(Option<CargoCheckMessage>),
440 CheckEvent(Option<CheckMessage>),
424441}
425442
426443/// This is stable behaviour. Don't change.
......@@ -511,7 +528,7 @@ impl FlycheckActor {
511528 command_handle: None,
512529 command_receiver: None,
513530 diagnostics_cleared_for: Default::default(),
514 diagnostics_received: DiagnosticsReceived::No,
531 diagnostics_received: DiagnosticsReceived::NotYet,
515532 }
516533 }
517534
......@@ -563,23 +580,13 @@ impl FlycheckActor {
563580 };
564581
565582 let debug_command = format!("{command:?}");
566 let user_facing_command = match origin {
567 // Don't show all the --format=json-with-blah-blah args, just the simple
568 // version
569 FlycheckCommandOrigin::Cargo => self.config.to_string(),
570 // show them the full command but pretty printed. advanced user
571 FlycheckCommandOrigin::ProjectJsonRunnable
572 | FlycheckCommandOrigin::CheckOverrideCommand => display_command(
573 &command,
574 Some(std::path::Path::new(self.root.as_path())),
575 ),
576 };
583 let user_facing_command = self.config.to_string();
577584
578585 tracing::debug!(?origin, ?command, "will restart flycheck");
579586 let (sender, receiver) = unbounded();
580587 match CommandHandle::spawn(
581588 command,
582 CargoCheckParser,
589 CheckParser,
583590 sender,
584591 match &self.config {
585592 FlycheckConfig::Automatic { cargo_options, .. } => {
......@@ -640,7 +647,7 @@ impl FlycheckActor {
640647 error
641648 );
642649 }
643 if self.diagnostics_received == DiagnosticsReceived::No {
650 if self.diagnostics_received == DiagnosticsReceived::NotYet {
644651 tracing::trace!(flycheck_id = self.id, "clearing diagnostics");
645652 // We finished without receiving any diagnostics.
646653 // Clear everything for good measure
......@@ -699,7 +706,7 @@ impl FlycheckActor {
699706 self.report_progress(Progress::DidFinish(res));
700707 }
701708 Event::CheckEvent(Some(message)) => match message {
702 CargoCheckMessage::CompilerArtifact(msg) => {
709 CheckMessage::CompilerArtifact(msg) => {
703710 tracing::trace!(
704711 flycheck_id = self.id,
705712 artifact = msg.target.name,
......@@ -729,46 +736,75 @@ impl FlycheckActor {
729736 });
730737 }
731738 }
732 CargoCheckMessage::Diagnostic { diagnostic, package_id } => {
739 CheckMessage::Diagnostic { diagnostic, package_id } => {
733740 tracing::trace!(
734741 flycheck_id = self.id,
735742 message = diagnostic.message,
736743 package_id = package_id.as_ref().map(|it| it.as_str()),
744 scope = ?self.scope,
737745 "diagnostic received"
738746 );
739 if self.diagnostics_received == DiagnosticsReceived::No {
740 self.diagnostics_received = DiagnosticsReceived::Yes;
741 }
742 if let Some(package_id) = &package_id {
743 if self.diagnostics_cleared_for.insert(package_id.clone()) {
744 tracing::trace!(
745 flycheck_id = self.id,
746 package_id = package_id.as_str(),
747 "clearing diagnostics"
748 );
749 self.send(FlycheckMessage::ClearDiagnostics {
747
748 match &self.scope {
749 FlycheckScope::Workspace => {
750 if self.diagnostics_received == DiagnosticsReceived::NotYet {
751 self.send(FlycheckMessage::ClearDiagnostics {
752 id: self.id,
753 kind: ClearDiagnosticsKind::All(ClearScope::Workspace),
754 });
755
756 self.diagnostics_received =
757 DiagnosticsReceived::AtLeastOneAndClearedWorkspace;
758 }
759
760 if let Some(package_id) = package_id {
761 tracing::warn!(
762 "Ignoring package label {:?} and applying diagnostics to the whole workspace",
763 package_id
764 );
765 }
766
767 self.send(FlycheckMessage::AddDiagnostic {
750768 id: self.id,
751 kind: ClearDiagnosticsKind::All(ClearScope::Package(
752 package_id.clone(),
753 )),
769 generation: self.generation,
770 package_id: None,
771 workspace_root: self.root.clone(),
772 diagnostic,
773 });
774 }
775 FlycheckScope::Package { package: flycheck_package, .. } => {
776 if self.diagnostics_received == DiagnosticsReceived::NotYet {
777 self.diagnostics_received = DiagnosticsReceived::AtLeastOne;
778 }
779
780 // If the package has been set in the diagnostic JSON, respect that. Otherwise, use the
781 // package that the current flycheck is scoped to. This is useful when a project is
782 // directly using rustc for its checks (e.g. custom check commands in rust-project.json).
783 let package_id = package_id.unwrap_or(flycheck_package.clone());
784
785 if self.diagnostics_cleared_for.insert(package_id.clone()) {
786 tracing::trace!(
787 flycheck_id = self.id,
788 package_id = package_id.as_str(),
789 "clearing diagnostics"
790 );
791 self.send(FlycheckMessage::ClearDiagnostics {
792 id: self.id,
793 kind: ClearDiagnosticsKind::All(ClearScope::Package(
794 package_id.clone(),
795 )),
796 });
797 }
798
799 self.send(FlycheckMessage::AddDiagnostic {
800 id: self.id,
801 generation: self.generation,
802 package_id: Some(package_id),
803 workspace_root: self.root.clone(),
804 diagnostic,
754805 });
755806 }
756 } else if self.diagnostics_received
757 != DiagnosticsReceived::YesAndClearedForAll
758 {
759 self.diagnostics_received = DiagnosticsReceived::YesAndClearedForAll;
760 self.send(FlycheckMessage::ClearDiagnostics {
761 id: self.id,
762 kind: ClearDiagnosticsKind::All(ClearScope::Workspace),
763 });
764807 }
765 self.send(FlycheckMessage::AddDiagnostic {
766 id: self.id,
767 generation: self.generation,
768 package_id,
769 workspace_root: self.root.clone(),
770 diagnostic,
771 });
772808 }
773809 },
774810 }
......@@ -792,7 +828,7 @@ impl FlycheckActor {
792828
793829 fn clear_diagnostics_state(&mut self) {
794830 self.diagnostics_cleared_for.clear();
795 self.diagnostics_received = DiagnosticsReceived::No;
831 self.diagnostics_received = DiagnosticsReceived::NotYet;
796832 }
797833
798834 fn explicit_check_command(
......@@ -942,15 +978,18 @@ impl FlycheckActor {
942978}
943979
944980#[allow(clippy::large_enum_variant)]
945enum CargoCheckMessage {
981enum CheckMessage {
982 /// A message from `cargo check`, including details like the path
983 /// to the relevant `Cargo.toml`.
946984 CompilerArtifact(cargo_metadata::Artifact),
985 /// A diagnostic message from rustc itself.
947986 Diagnostic { diagnostic: Diagnostic, package_id: Option<PackageSpecifier> },
948987}
949988
950struct CargoCheckParser;
989struct CheckParser;
951990
952impl JsonLinesParser<CargoCheckMessage> for CargoCheckParser {
953 fn from_line(&self, line: &str, error: &mut String) -> Option<CargoCheckMessage> {
991impl JsonLinesParser<CheckMessage> for CheckParser {
992 fn from_line(&self, line: &str, error: &mut String) -> Option<CheckMessage> {
954993 let mut deserializer = serde_json::Deserializer::from_str(line);
955994 deserializer.disable_recursion_limit();
956995 if let Ok(message) = JsonMessage::deserialize(&mut deserializer) {
......@@ -958,10 +997,10 @@ impl JsonLinesParser<CargoCheckMessage> for CargoCheckParser {
958997 // Skip certain kinds of messages to only spend time on what's useful
959998 JsonMessage::Cargo(message) => match message {
960999 cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => {
961 Some(CargoCheckMessage::CompilerArtifact(artifact))
1000 Some(CheckMessage::CompilerArtifact(artifact))
9621001 }
9631002 cargo_metadata::Message::CompilerMessage(msg) => {
964 Some(CargoCheckMessage::Diagnostic {
1003 Some(CheckMessage::Diagnostic {
9651004 diagnostic: msg.message,
9661005 package_id: Some(PackageSpecifier::Cargo {
9671006 package_id: Arc::new(msg.package_id),
......@@ -971,7 +1010,7 @@ impl JsonLinesParser<CargoCheckMessage> for CargoCheckParser {
9711010 _ => None,
9721011 },
9731012 JsonMessage::Rustc(message) => {
974 Some(CargoCheckMessage::Diagnostic { diagnostic: message, package_id: None })
1013 Some(CheckMessage::Diagnostic { diagnostic: message, package_id: None })
9751014 }
9761015 };
9771016 }
......@@ -981,7 +1020,7 @@ impl JsonLinesParser<CargoCheckMessage> for CargoCheckParser {
9811020 None
9821021 }
9831022
984 fn from_eof(&self) -> Option<CargoCheckMessage> {
1023 fn from_eof(&self) -> Option<CheckMessage> {
9851024 None
9861025 }
9871026}
......@@ -993,64 +1032,14 @@ enum JsonMessage {
9931032 Rustc(Diagnostic),
9941033}
9951034
996/// Not good enough to execute in a shell, but good enough to show the user without all the noisy
997/// quotes
998///
999/// Pass implicit_cwd if there is one regarded as the obvious by the user, so we can skip showing it.
1000/// Compactness is the aim of the game, the output typically gets truncated quite a lot.
1001fn display_command(c: &Command, implicit_cwd: Option<&std::path::Path>) -> String {
1002 let mut o = String::new();
1003 use std::fmt::Write;
1004 let lossy = std::ffi::OsStr::to_string_lossy;
1005 if let Some(dir) = c.get_current_dir() {
1006 if Some(dir) == implicit_cwd.map(std::path::Path::new) {
1007 // pass
1008 } else if dir.to_string_lossy().contains(" ") {
1009 write!(o, "cd {:?} && ", dir).unwrap();
1010 } else {
1011 write!(o, "cd {} && ", dir.display()).unwrap();
1012 }
1013 }
1014 for (env, val) in c.get_envs() {
1015 let (env, val) = (lossy(env), val.map(lossy).unwrap_or(std::borrow::Cow::Borrowed("")));
1016 if DISPLAY_COMMAND_IGNORE_ENVS.contains(&env.as_ref()) {
1017 continue;
1018 }
1019 if env.contains(" ") {
1020 write!(o, "\"{}={}\" ", env, val).unwrap();
1021 } else if val.contains(" ") {
1022 write!(o, "{}=\"{}\" ", env, val).unwrap();
1023 } else {
1024 write!(o, "{}={} ", env, val).unwrap();
1025 }
1026 }
1027 let prog = lossy(c.get_program());
1028 if prog.contains(" ") {
1029 write!(o, "{:?}", prog).unwrap();
1030 } else {
1031 write!(o, "{}", prog).unwrap();
1032 }
1033 for arg in c.get_args() {
1034 let arg = lossy(arg);
1035 if arg.contains(" ") {
1036 write!(o, " \"{}\"", arg).unwrap();
1037 } else {
1038 write!(o, " {}", arg).unwrap();
1039 }
1040 }
1041 o
1042}
1043
10441035#[cfg(test)]
10451036mod tests {
1037 use super::*;
10461038 use ide_db::FxHashMap;
10471039 use itertools::Itertools;
10481040 use paths::Utf8Path;
10491041 use project_model::project_json;
10501042
1051 use crate::flycheck::Substitutions;
1052 use crate::flycheck::display_command;
1053
10541043 #[test]
10551044 fn test_substitutions() {
10561045 let label = ":label";
......@@ -1139,34 +1128,47 @@ mod tests {
11391128 }
11401129
11411130 #[test]
1142 fn test_display_command() {
1143 use std::path::Path;
1144 let workdir = Path::new("workdir");
1145 let mut cmd = toolchain::command("command", workdir, &FxHashMap::default());
1146 assert_eq!(display_command(cmd.arg("--arg"), Some(workdir)), "command --arg");
1147 assert_eq!(
1148 display_command(cmd.arg("spaced arg"), Some(workdir)),
1149 "command --arg \"spaced arg\""
1150 );
1151 assert_eq!(
1152 display_command(cmd.env("ENVIRON", "yeah"), Some(workdir)),
1153 "ENVIRON=yeah command --arg \"spaced arg\""
1154 );
1155 assert_eq!(
1156 display_command(cmd.env("OTHER", "spaced env"), Some(workdir)),
1157 "ENVIRON=yeah OTHER=\"spaced env\" command --arg \"spaced arg\""
1158 );
1159 assert_eq!(
1160 display_command(cmd.current_dir("/tmp"), Some(workdir)),
1161 "cd /tmp && ENVIRON=yeah OTHER=\"spaced env\" command --arg \"spaced arg\""
1162 );
1163 assert_eq!(
1164 display_command(cmd.current_dir("/tmp and/thing"), Some(workdir)),
1165 "cd \"/tmp and/thing\" && ENVIRON=yeah OTHER=\"spaced env\" command --arg \"spaced arg\""
1166 );
1167 assert_eq!(
1168 display_command(cmd.current_dir("/tmp and/thing"), Some(Path::new("/tmp and/thing"))),
1169 "ENVIRON=yeah OTHER=\"spaced env\" command --arg \"spaced arg\""
1170 );
1131 fn test_flycheck_config_display() {
1132 let clippy = FlycheckConfig::Automatic {
1133 cargo_options: CargoOptions {
1134 subcommand: "clippy".to_owned(),
1135 target_tuples: vec![],
1136 all_targets: false,
1137 set_test: false,
1138 no_default_features: false,
1139 all_features: false,
1140 features: vec![],
1141 extra_args: vec![],
1142 extra_test_bin_args: vec![],
1143 extra_env: FxHashMap::default(),
1144 target_dir_config: TargetDirectoryConfig::default(),
1145 },
1146 ansi_color_output: true,
1147 };
1148 assert_eq!(clippy.to_string(), "cargo clippy");
1149
1150 let custom_dollar = FlycheckConfig::CustomCommand {
1151 command: "check".to_owned(),
1152 args: vec!["--input".to_owned(), "$saved_file".to_owned()],
1153 extra_env: FxHashMap::default(),
1154 invocation_strategy: InvocationStrategy::Once,
1155 };
1156 assert_eq!(custom_dollar.to_string(), "check --input ...");
1157
1158 let custom_inline = FlycheckConfig::CustomCommand {
1159 command: "check".to_owned(),
1160 args: vec!["--input".to_owned(), "{saved_file}".to_owned()],
1161 extra_env: FxHashMap::default(),
1162 invocation_strategy: InvocationStrategy::Once,
1163 };
1164 assert_eq!(custom_inline.to_string(), "check --input ...");
1165
1166 let custom_rs = FlycheckConfig::CustomCommand {
1167 command: "check".to_owned(),
1168 args: vec!["--input".to_owned(), "/path/to/file.rs".to_owned()],
1169 extra_env: FxHashMap::default(),
1170 invocation_strategy: InvocationStrategy::Once,
1171 };
1172 assert_eq!(custom_rs.to_string(), "check --input ...");
11711173 }
11721174}
src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs+7-1
......@@ -14,7 +14,7 @@ use hir::ChangeWithProcMacros;
1414use ide::{Analysis, AnalysisHost, Cancellable, FileId, SourceRootId};
1515use ide_db::{
1616 MiniCore,
17 base_db::{Crate, ProcMacroPaths, SourceDatabase, salsa::Revision},
17 base_db::{Crate, ProcMacroPaths, SourceDatabase, salsa::CancellationToken, salsa::Revision},
1818};
1919use itertools::Itertools;
2020use load_cargo::SourceRootConfig;
......@@ -88,6 +88,7 @@ pub(crate) struct GlobalState {
8888 pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
8989 pub(crate) fmt_pool: Handle<TaskPool<Task>, Receiver<Task>>,
9090 pub(crate) cancellation_pool: thread::Pool,
91 pub(crate) cancellation_tokens: FxHashMap<lsp_server::RequestId, CancellationToken>,
9192
9293 pub(crate) config: Arc<Config>,
9394 pub(crate) config_errors: Option<ConfigErrors>,
......@@ -265,6 +266,7 @@ impl GlobalState {
265266 task_pool,
266267 fmt_pool,
267268 cancellation_pool,
269 cancellation_tokens: Default::default(),
268270 loader,
269271 config: Arc::new(config.clone()),
270272 analysis_host,
......@@ -617,6 +619,7 @@ impl GlobalState {
617619 }
618620
619621 pub(crate) fn respond(&mut self, response: lsp_server::Response) {
622 self.cancellation_tokens.remove(&response.id);
620623 if let Some((method, start)) = self.req_queue.incoming.complete(&response.id) {
621624 if let Some(err) = &response.error
622625 && err.message.starts_with("server panicked")
......@@ -631,6 +634,9 @@ impl GlobalState {
631634 }
632635
633636 pub(crate) fn cancel(&mut self, request_id: lsp_server::RequestId) {
637 if let Some(token) = self.cancellation_tokens.remove(&request_id) {
638 token.cancel();
639 }
634640 if let Some(response) = self.req_queue.incoming.cancel(request_id) {
635641 self.send(response.into());
636642 }
src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs+16-1
......@@ -253,6 +253,9 @@ impl RequestDispatcher<'_> {
253253 tracing::debug!(?params);
254254
255255 let world = self.global_state.snapshot();
256 self.global_state
257 .cancellation_tokens
258 .insert(req.id.clone(), world.analysis.cancellation_token());
256259 if RUSTFMT {
257260 &mut self.global_state.fmt_pool.handle
258261 } else {
......@@ -265,7 +268,19 @@ impl RequestDispatcher<'_> {
265268 });
266269 match thread_result_to_response::<R>(req.id.clone(), result) {
267270 Ok(response) => Task::Response(response),
268 Err(_cancelled) if ALLOW_RETRYING => Task::Retry(req),
271 Err(HandlerCancelledError::Inner(
272 Cancelled::PendingWrite | Cancelled::PropagatedPanic,
273 )) if ALLOW_RETRYING => Task::Retry(req),
274 // Note: Technically the return value here does not matter as we have already responded to the client with this error.
275 Err(HandlerCancelledError::Inner(Cancelled::Local)) => Task::Response(Response {
276 id: req.id,
277 result: None,
278 error: Some(ResponseError {
279 code: lsp_server::ErrorCode::RequestCanceled as i32,
280 message: "canceled by client".to_owned(),
281 data: None,
282 }),
283 }),
269284 Err(_cancelled) => {
270285 let error = on_cancelled();
271286 Task::Response(Response { id: req.id, result: None, error: Some(error) })
src/tools/rust-analyzer/crates/span/src/hygiene.rs+25-26
......@@ -81,25 +81,24 @@ const _: () = {
8181 #[derive(Hash)]
8282 struct StructKey<'db, T0, T1, T2, T3>(T0, T1, T2, T3, std::marker::PhantomData<&'db ()>);
8383
84 impl<'db, T0, T1, T2, T3> zalsa_::interned::HashEqLike<StructKey<'db, T0, T1, T2, T3>>
85 for SyntaxContextData
84 impl<'db, T0, T1, T2, T3> zalsa_::HashEqLike<StructKey<'db, T0, T1, T2, T3>> for SyntaxContextData
8685 where
87 Option<MacroCallId>: zalsa_::interned::HashEqLike<T0>,
88 Transparency: zalsa_::interned::HashEqLike<T1>,
89 Edition: zalsa_::interned::HashEqLike<T2>,
90 SyntaxContext: zalsa_::interned::HashEqLike<T3>,
86 Option<MacroCallId>: zalsa_::HashEqLike<T0>,
87 Transparency: zalsa_::HashEqLike<T1>,
88 Edition: zalsa_::HashEqLike<T2>,
89 SyntaxContext: zalsa_::HashEqLike<T3>,
9190 {
9291 fn hash<H: std::hash::Hasher>(&self, h: &mut H) {
93 zalsa_::interned::HashEqLike::<T0>::hash(&self.outer_expn, &mut *h);
94 zalsa_::interned::HashEqLike::<T1>::hash(&self.outer_transparency, &mut *h);
95 zalsa_::interned::HashEqLike::<T2>::hash(&self.edition, &mut *h);
96 zalsa_::interned::HashEqLike::<T3>::hash(&self.parent, &mut *h);
92 zalsa_::HashEqLike::<T0>::hash(&self.outer_expn, &mut *h);
93 zalsa_::HashEqLike::<T1>::hash(&self.outer_transparency, &mut *h);
94 zalsa_::HashEqLike::<T2>::hash(&self.edition, &mut *h);
95 zalsa_::HashEqLike::<T3>::hash(&self.parent, &mut *h);
9796 }
9897 fn eq(&self, data: &StructKey<'db, T0, T1, T2, T3>) -> bool {
99 zalsa_::interned::HashEqLike::<T0>::eq(&self.outer_expn, &data.0)
100 && zalsa_::interned::HashEqLike::<T1>::eq(&self.outer_transparency, &data.1)
101 && zalsa_::interned::HashEqLike::<T2>::eq(&self.edition, &data.2)
102 && zalsa_::interned::HashEqLike::<T3>::eq(&self.parent, &data.3)
98 zalsa_::HashEqLike::<T0>::eq(&self.outer_expn, &data.0)
99 && zalsa_::HashEqLike::<T1>::eq(&self.outer_transparency, &data.1)
100 && zalsa_::HashEqLike::<T2>::eq(&self.edition, &data.2)
101 && zalsa_::HashEqLike::<T3>::eq(&self.parent, &data.3)
103102 }
104103 }
105104 impl zalsa_struct_::Configuration for SyntaxContext {
......@@ -203,10 +202,10 @@ const _: () = {
203202 impl<'db> SyntaxContext {
204203 pub fn new<
205204 Db,
206 T0: zalsa_::interned::Lookup<Option<MacroCallId>> + std::hash::Hash,
207 T1: zalsa_::interned::Lookup<Transparency> + std::hash::Hash,
208 T2: zalsa_::interned::Lookup<Edition> + std::hash::Hash,
209 T3: zalsa_::interned::Lookup<SyntaxContext> + std::hash::Hash,
205 T0: zalsa_::Lookup<Option<MacroCallId>> + std::hash::Hash,
206 T1: zalsa_::Lookup<Transparency> + std::hash::Hash,
207 T2: zalsa_::Lookup<Edition> + std::hash::Hash,
208 T3: zalsa_::Lookup<SyntaxContext> + std::hash::Hash,
210209 >(
211210 db: &'db Db,
212211 outer_expn: T0,
......@@ -218,10 +217,10 @@ const _: () = {
218217 ) -> Self
219218 where
220219 Db: ?Sized + salsa::Database,
221 Option<MacroCallId>: zalsa_::interned::HashEqLike<T0>,
222 Transparency: zalsa_::interned::HashEqLike<T1>,
223 Edition: zalsa_::interned::HashEqLike<T2>,
224 SyntaxContext: zalsa_::interned::HashEqLike<T3>,
220 Option<MacroCallId>: zalsa_::HashEqLike<T0>,
221 Transparency: zalsa_::HashEqLike<T1>,
222 Edition: zalsa_::HashEqLike<T2>,
223 SyntaxContext: zalsa_::HashEqLike<T3>,
225224 {
226225 let (zalsa, zalsa_local) = db.zalsas();
227226
......@@ -236,10 +235,10 @@ const _: () = {
236235 std::marker::PhantomData,
237236 ),
238237 |id, data| SyntaxContextData {
239 outer_expn: zalsa_::interned::Lookup::into_owned(data.0),
240 outer_transparency: zalsa_::interned::Lookup::into_owned(data.1),
241 edition: zalsa_::interned::Lookup::into_owned(data.2),
242 parent: zalsa_::interned::Lookup::into_owned(data.3),
238 outer_expn: zalsa_::Lookup::into_owned(data.0),
239 outer_transparency: zalsa_::Lookup::into_owned(data.1),
240 edition: zalsa_::Lookup::into_owned(data.2),
241 parent: zalsa_::Lookup::into_owned(data.3),
243242 opaque: opaque(zalsa_::FromId::from_id(id)),
244243 opaque_and_semiopaque: opaque_and_semiopaque(zalsa_::FromId::from_id(id)),
245244 },
src/tools/rust-analyzer/crates/syntax/rust.ungram+4-1
......@@ -472,8 +472,11 @@ RefExpr =
472472TryExpr =
473473 Attr* Expr '?'
474474
475TryBlockModifier =
476 'try' ('bikeshed' Type)?
477
475478BlockExpr =
476 Attr* Label? ('try' | 'unsafe' | ('async' 'move'?) | ('gen' 'move'?) | 'const') StmtList
479 Attr* Label? (TryBlockModifier | 'unsafe' | ('async' 'move'?) | ('gen' 'move'?) | 'const') StmtList
477480
478481PrefixExpr =
479482 Attr* op:('-' | '!' | '*') Expr
src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs+12-2
......@@ -375,7 +375,11 @@ impl ast::Literal {
375375pub enum BlockModifier {
376376 Async(SyntaxToken),
377377 Unsafe(SyntaxToken),
378 Try(SyntaxToken),
378 Try {
379 try_token: SyntaxToken,
380 bikeshed_token: Option<SyntaxToken>,
381 result_type: Option<ast::Type>,
382 },
379383 Const(SyntaxToken),
380384 AsyncGen(SyntaxToken),
381385 Gen(SyntaxToken),
......@@ -394,7 +398,13 @@ impl ast::BlockExpr {
394398 })
395399 .or_else(|| self.async_token().map(BlockModifier::Async))
396400 .or_else(|| self.unsafe_token().map(BlockModifier::Unsafe))
397 .or_else(|| self.try_token().map(BlockModifier::Try))
401 .or_else(|| {
402 let modifier = self.try_block_modifier()?;
403 let try_token = modifier.try_token()?;
404 let bikeshed_token = modifier.bikeshed_token();
405 let result_type = modifier.ty();
406 Some(BlockModifier::Try { try_token, bikeshed_token, result_type })
407 })
398408 .or_else(|| self.const_token().map(BlockModifier::Const))
399409 .or_else(|| self.label().map(BlockModifier::Label))
400410 }
src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs+52-2
......@@ -323,6 +323,8 @@ impl BlockExpr {
323323 #[inline]
324324 pub fn stmt_list(&self) -> Option<StmtList> { support::child(&self.syntax) }
325325 #[inline]
326 pub fn try_block_modifier(&self) -> Option<TryBlockModifier> { support::child(&self.syntax) }
327 #[inline]
326328 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
327329 #[inline]
328330 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
......@@ -331,8 +333,6 @@ impl BlockExpr {
331333 #[inline]
332334 pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
333335 #[inline]
334 pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
335 #[inline]
336336 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
337337}
338338pub struct BoxPat {
......@@ -1630,6 +1630,19 @@ impl Trait {
16301630 #[inline]
16311631 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
16321632}
1633pub struct TryBlockModifier {
1634 pub(crate) syntax: SyntaxNode,
1635}
1636impl TryBlockModifier {
1637 #[inline]
1638 pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
1639 #[inline]
1640 pub fn bikeshed_token(&self) -> Option<SyntaxToken> {
1641 support::token(&self.syntax, T![bikeshed])
1642 }
1643 #[inline]
1644 pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
1645}
16331646pub struct TryExpr {
16341647 pub(crate) syntax: SyntaxNode,
16351648}
......@@ -6320,6 +6333,38 @@ impl fmt::Debug for Trait {
63206333 f.debug_struct("Trait").field("syntax", &self.syntax).finish()
63216334 }
63226335}
6336impl AstNode for TryBlockModifier {
6337 #[inline]
6338 fn kind() -> SyntaxKind
6339 where
6340 Self: Sized,
6341 {
6342 TRY_BLOCK_MODIFIER
6343 }
6344 #[inline]
6345 fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_BLOCK_MODIFIER }
6346 #[inline]
6347 fn cast(syntax: SyntaxNode) -> Option<Self> {
6348 if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
6349 }
6350 #[inline]
6351 fn syntax(&self) -> &SyntaxNode { &self.syntax }
6352}
6353impl hash::Hash for TryBlockModifier {
6354 fn hash<H: hash::Hasher>(&self, state: &mut H) { self.syntax.hash(state); }
6355}
6356impl Eq for TryBlockModifier {}
6357impl PartialEq for TryBlockModifier {
6358 fn eq(&self, other: &Self) -> bool { self.syntax == other.syntax }
6359}
6360impl Clone for TryBlockModifier {
6361 fn clone(&self) -> Self { Self { syntax: self.syntax.clone() } }
6362}
6363impl fmt::Debug for TryBlockModifier {
6364 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6365 f.debug_struct("TryBlockModifier").field("syntax", &self.syntax).finish()
6366 }
6367}
63236368impl AstNode for TryExpr {
63246369 #[inline]
63256370 fn kind() -> SyntaxKind
......@@ -9979,6 +10024,11 @@ impl std::fmt::Display for Trait {
997910024 std::fmt::Display::fmt(self.syntax(), f)
998010025 }
998110026}
10027impl std::fmt::Display for TryBlockModifier {
10028 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10029 std::fmt::Display::fmt(self.syntax(), f)
10030 }
10031}
998210032impl std::fmt::Display for TryExpr {
998310033 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
998410034 std::fmt::Display::fmt(self.syntax(), f)
src/tools/rust-analyzer/crates/syntax/src/syntax_error.rs-10
......@@ -9,16 +9,6 @@ use crate::{TextRange, TextSize};
99#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1010pub struct SyntaxError(String, TextRange);
1111
12// FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed)
13// It was introduced in this PR: https://github.com/rust-lang/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95
14// but it was not removed by a mistake.
15//
16// So, we need to find a place where to stick validation for attributes in match clauses.
17// Code before refactor:
18// InvalidMatchInnerAttr => {
19// write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
20// }
21
2212impl SyntaxError {
2313 pub fn new(message: impl Into<String>, range: TextRange) -> Self {
2414 Self(message.into(), range)
src/tools/rust-analyzer/crates/test-utils/src/minicore.rs+31-1
......@@ -43,6 +43,7 @@
4343//! dispatch_from_dyn: unsize, pin
4444//! hash: sized
4545//! include:
46//! include_bytes:
4647//! index: sized
4748//! infallible:
4849//! int_impl: size_of, transmute
......@@ -953,6 +954,9 @@ pub mod ops {
953954 #[lang = "from_residual"]
954955 fn from_residual(residual: R) -> Self;
955956 }
957 pub const trait Residual<O>: Sized {
958 type TryType: [const] Try<Output = O, Residual = Self>;
959 }
956960 #[lang = "Try"]
957961 pub trait Try: FromResidual<Self::Residual> {
958962 type Output;
......@@ -962,6 +966,12 @@ pub mod ops {
962966 #[lang = "branch"]
963967 fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
964968 }
969 #[lang = "into_try_type"]
970 pub const fn residual_into_try_type<R: [const] Residual<O>, O>(
971 r: R,
972 ) -> <R as Residual<O>>::TryType {
973 FromResidual::from_residual(r)
974 }
965975
966976 impl<B, C> Try for ControlFlow<B, C> {
967977 type Output = C;
......@@ -985,6 +995,10 @@ pub mod ops {
985995 }
986996 }
987997 }
998
999 impl<B, C> Residual<C> for ControlFlow<B, Infallible> {
1000 type TryType = ControlFlow<B, C>;
1001 }
9881002 // region:option
9891003 impl<T> Try for Option<T> {
9901004 type Output = T;
......@@ -1008,6 +1022,10 @@ pub mod ops {
10081022 }
10091023 }
10101024 }
1025
1026 impl<T> const Residual<T> for Option<Infallible> {
1027 type TryType = Option<T>;
1028 }
10111029 // endregion:option
10121030 // region:result
10131031 // region:from
......@@ -1037,10 +1055,14 @@ pub mod ops {
10371055 }
10381056 }
10391057 }
1058
1059 impl<T, E> const Residual<T> for Result<Infallible, E> {
1060 type TryType = Result<T, E>;
1061 }
10401062 // endregion:from
10411063 // endregion:result
10421064 }
1043 pub use self::try_::{ControlFlow, FromResidual, Try};
1065 pub use self::try_::{ControlFlow, FromResidual, Residual, Try};
10441066 // endregion:try
10451067
10461068 // region:add
......@@ -2040,6 +2062,14 @@ mod macros {
20402062 }
20412063 // endregion:include
20422064
2065 // region:include_bytes
2066 #[rustc_builtin_macro]
2067 #[macro_export]
2068 macro_rules! include_bytes {
2069 ($file:expr $(,)?) => {{ /* compiler built-in */ }};
2070 }
2071 // endregion:include_bytes
2072
20432073 // region:concat
20442074 #[rustc_builtin_macro]
20452075 #[macro_export]
src/tools/rust-analyzer/crates/toolchain/src/lib.rs-3
......@@ -74,9 +74,6 @@ impl Tool {
7474// Prevent rustup from automatically installing toolchains, see https://github.com/rust-lang/rust-analyzer/issues/20719.
7575pub const NO_RUSTUP_AUTO_INSTALL_ENV: (&str, &str) = ("RUSTUP_AUTO_INSTALL", "0");
7676
77// These get ignored when displaying what command is running in LSP status messages.
78pub const DISPLAY_COMMAND_IGNORE_ENVS: &[&str] = &[NO_RUSTUP_AUTO_INSTALL_ENV.0];
79
8077#[allow(clippy::disallowed_types)] /* generic parameter allows for FxHashMap */
8178pub fn command<H>(
8279 cmd: impl AsRef<OsStr>,
src/tools/rust-analyzer/docs/book/README.md+1-1
......@@ -6,7 +6,7 @@ The rust analyzer manual uses [mdbook](https://rust-lang.github.io/mdBook/).
66
77To run the documentation site locally:
88
9```shell
9```bash
1010cargo install mdbook
1111cargo xtask codegen
1212cd docs/book
src/tools/rust-analyzer/docs/book/src/contributing/README.md+6-5
......@@ -4,7 +4,7 @@ rust-analyzer is an ordinary Rust project, which is organized as a Cargo workspa
44So, just
55
66```bash
7$ cargo test
7cargo test
88```
99
1010should be enough to get you started!
......@@ -203,14 +203,14 @@ It is enabled by `RA_COUNT=1`.
203203To measure time for from-scratch analysis, use something like this:
204204
205205```bash
206$ cargo run --release -p rust-analyzer -- analysis-stats ../chalk/
206cargo run --release -p rust-analyzer -- analysis-stats ../chalk/
207207```
208208
209209For measuring time of incremental analysis, use either of these:
210210
211211```bash
212$ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --highlight ../chalk/chalk-engine/src/logic.rs
213$ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0
212cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --highlight ../chalk/chalk-engine/src/logic.rs
213cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0
214214```
215215
216216Look for `fn benchmark_xxx` tests for a quick way to reproduce performance problems.
......@@ -283,7 +283,8 @@ repository. We use the [rustc-josh-sync](https://github.com/rust-lang/josh-sync)
283283repositories. You can find documentation of the tool [here](https://github.com/rust-lang/josh-sync).
284284
285285You can install the synchronization tool using the following commands:
286```
286
287```bash
287288cargo install --locked --git https://github.com/rust-lang/josh-sync
288289```
289290
src/tools/rust-analyzer/docs/book/src/contributing/debugging.md+1-1
......@@ -68,7 +68,7 @@ while d == 4 { // set a breakpoint here and change the value
6868
6969However for this to work, you will need to enable debug_assertions in your build
7070
71```rust
71```bash
7272RUSTFLAGS='--cfg debug_assertions' cargo build --release
7373```
7474
src/tools/rust-analyzer/docs/book/src/installation.md+3-1
......@@ -13,7 +13,9 @@ editor](./other_editors.html).
1313rust-analyzer will attempt to install the standard library source code
1414automatically. You can also install it manually with `rustup`.
1515
16 $ rustup component add rust-src
16```bash
17rustup component add rust-src
18```
1719
1820Only the latest stable standard library source is officially supported
1921for use with rust-analyzer. If you are using an older toolchain or have
src/tools/rust-analyzer/docs/book/src/rust_analyzer_binary.md+18-8
......@@ -11,9 +11,11 @@ your `$PATH`.
1111On Linux to install the `rust-analyzer` binary into `~/.local/bin`,
1212these commands should work:
1313
14 $ mkdir -p ~/.local/bin
15 $ curl -L https://github.com/rust-lang/rust-analyzer/releases/latest/download/rust-analyzer-x86_64-unknown-linux-gnu.gz | gunzip -c - > ~/.local/bin/rust-analyzer
16 $ chmod +x ~/.local/bin/rust-analyzer
14```bash
15mkdir -p ~/.local/bin
16curl -L https://github.com/rust-lang/rust-analyzer/releases/latest/download/rust-analyzer-x86_64-unknown-linux-gnu.gz | gunzip -c - > ~/.local/bin/rust-analyzer
17chmod +x ~/.local/bin/rust-analyzer
18```
1719
1820Make sure that `~/.local/bin` is listed in the `$PATH` variable and use
1921the appropriate URL if you’re not on a `x86-64` system.
......@@ -24,8 +26,10 @@ or `/usr/local/bin` will work just as well.
2426Alternatively, you can install it from source using the command below.
2527You’ll need the latest stable version of the Rust toolchain.
2628
27 $ git clone https://github.com/rust-lang/rust-analyzer.git && cd rust-analyzer
28 $ cargo xtask install --server
29```bash
30git clone https://github.com/rust-lang/rust-analyzer.git && cd rust-analyzer
31cargo xtask install --server
32```
2933
3034If your editor can’t find the binary even though the binary is on your
3135`$PATH`, the likely explanation is that it doesn’t see the same `$PATH`
......@@ -38,7 +42,9 @@ the environment should help.
3842
3943`rust-analyzer` is available in `rustup`:
4044
41 $ rustup component add rust-analyzer
45```bash
46rustup component add rust-analyzer
47```
4248
4349### Arch Linux
4450
......@@ -53,7 +59,9 @@ User Repository):
5359
5460Install it with pacman, for example:
5561
56 $ pacman -S rust-analyzer
62```bash
63pacman -S rust-analyzer
64```
5765
5866### Gentoo Linux
5967
......@@ -64,7 +72,9 @@ Install it with pacman, for example:
6472The `rust-analyzer` binary can be installed via
6573[Homebrew](https://brew.sh/).
6674
67 $ brew install rust-analyzer
75```bash
76brew install rust-analyzer
77```
6878
6979### Windows
7080
src/tools/rust-analyzer/docs/book/src/troubleshooting.md+5-5
......@@ -37,13 +37,13 @@ bypassing LSP machinery.
3737When filing issues, it is useful (but not necessary) to try to minimize
3838examples. An ideal bug reproduction looks like this:
3939
40```shell
41$ git clone https://github.com/username/repo.git && cd repo && git switch --detach commit-hash
42$ rust-analyzer --version
40```bash
41git clone https://github.com/username/repo.git && cd repo && git switch --detach commit-hash
42rust-analyzer --version
4343rust-analyzer dd12184e4 2021-05-08 dev
44$ rust-analyzer analysis-stats .
45💀 💀 💀
44rust-analyzer analysis-stats .
4645```
46💀 💀 💀
4747
4848It is especially useful when the `repo` doesn’t use external crates or
4949the standard library.
src/tools/rust-analyzer/docs/book/src/vs_code.md+10-5
......@@ -49,7 +49,9 @@ Alternatively, download a VSIX corresponding to your platform from the
4949Install the extension with the `Extensions: Install from VSIX` command
5050within VS Code, or from the command line via:
5151
52 $ code --install-extension /path/to/rust-analyzer.vsix
52```bash
53code --install-extension /path/to/rust-analyzer.vsix
54```
5355
5456If you are running an unsupported platform, you can install
5557`rust-analyzer-no-server.vsix` and compile or obtain a server binary.
......@@ -64,8 +66,10 @@ example:
6466
6567Both the server and the Code plugin can be installed from source:
6668
67 $ git clone https://github.com/rust-lang/rust-analyzer.git && cd rust-analyzer
68 $ cargo xtask install
69```bash
70git clone https://github.com/rust-lang/rust-analyzer.git && cd rust-analyzer
71cargo xtask install
72```
6973
7074You’ll need Cargo, nodejs (matching a supported version of VS Code) and
7175npm for this.
......@@ -76,7 +80,9 @@ Remote, instead you’ll need to install the `.vsix` manually.
7680If you’re not using Code, you can compile and install only the LSP
7781server:
7882
79 $ cargo xtask install --server
83```bash
84cargo xtask install --server
85```
8086
8187Make sure that `.cargo/bin` is in `$PATH` and precedes paths where
8288`rust-analyzer` may also be installed. Specifically, `rustup` includes a
......@@ -118,4 +124,3 @@ steps might help:
118124
119125A C compiler should already be available via `org.freedesktop.Sdk`. Any
120126other tools or libraries you will need to acquire from Flatpak.
121
src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs+1-1
......@@ -112,7 +112,7 @@ const RESERVED: &[&str] = &[
112112// keywords that are keywords only in specific parse contexts
113113#[doc(alias = "WEAK_KEYWORDS")]
114114const CONTEXTUAL_KEYWORDS: &[&str] =
115 &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet", "safe"];
115 &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet", "safe", "bikeshed"];
116116// keywords we use for special macro expansions
117117const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &[
118118 "asm",
tests/crashes/135470.rs deleted-41
......@@ -1,41 +0,0 @@
1//@ known-bug: #135470
2//@ compile-flags: -Copt-level=0
3//@ edition: 2021
4
5use std::future::Future;
6trait Access {
7 type Lister;
8
9 fn list() -> impl Future<Output = Self::Lister> {
10 async { todo!() }
11 }
12}
13
14trait Foo {}
15impl Access for dyn Foo {
16 type Lister = ();
17}
18
19fn main() {
20 let svc = async {
21 async { <dyn Foo>::list() }.await;
22 };
23 &svc as &dyn Service;
24}
25
26trait UnaryService {
27 fn call2() {}
28}
29trait Unimplemented {}
30impl<T: Unimplemented> UnaryService for T {}
31struct Wrap<T>(T);
32impl<T: Send> UnaryService for Wrap<T> {}
33
34trait Service {
35 fn call(&self);
36}
37impl<T: Send> Service for T {
38 fn call(&self) {
39 Wrap::<T>::call2();
40 }
41}
tests/crashes/137190-2.rs deleted-18
......@@ -1,18 +0,0 @@
1//@ known-bug: #137190
2trait Supertrait<T> {
3 fn method(&self) {}
4}
5
6trait Trait<P>: Supertrait<()> {}
7
8impl<P> Trait<P> for () {}
9
10const fn upcast<P>(x: &dyn Trait<P>) -> &dyn Supertrait<()> {
11 x
12}
13
14const fn foo() -> &'static dyn Supertrait<()> {
15 upcast::<()>(&())
16}
17
18const _: &'static dyn Supertrait<()> = foo();
tests/crashes/137190-3.rs deleted-10
......@@ -1,10 +0,0 @@
1//@ known-bug: #137190
2trait Supertrait {
3 fn method(&self) {}
4}
5
6trait Trait: Supertrait {}
7
8impl Trait for () {}
9
10const _: &dyn Supertrait = &() as &dyn Trait as &dyn Supertrait;
tests/crashes/137916.rs deleted-13
......@@ -1,13 +0,0 @@
1//@ known-bug: #137916
2//@ edition: 2021
3use std::ptr::null;
4
5async fn a() -> Box<dyn Send> {
6 Box::new(async {
7 let non_send = null::<()>();
8 &non_send;
9 async {}.await
10 })
11}
12
13fn main() {}
tests/crashes/138274.rs deleted-18
......@@ -1,18 +0,0 @@
1//@ known-bug: #138274
2//@ edition: 2021
3//@ compile-flags: --crate-type=lib
4trait Trait {}
5
6fn foo() -> Box<dyn Trait> {
7 todo!()
8}
9
10fn fetch() {
11 async {
12 let fut = async {
13 let _x = foo();
14 async {}.await;
15 };
16 let _: Box<dyn Send> = Box::new(fut);
17 };
18}
tests/run-make/wasm-emscripten-cdylib/foo.rs created+4
......@@ -0,0 +1,4 @@
1#[no_mangle]
2pub extern "C" fn foo() -> i32 {
3 42
4}
tests/run-make/wasm-emscripten-cdylib/rmake.rs created+25
......@@ -0,0 +1,25 @@
1//! Check that cdylib crate type is supported for the wasm32-unknown-emscripten
2//! target and produces a valid Emscripten dynamic library.
3
4//@ only-wasm32-unknown-emscripten
5
6use run_make_support::{bare_rustc, rfs, wasmparser};
7
8fn main() {
9 bare_rustc().input("foo.rs").target("wasm32-unknown-emscripten").crate_type("cdylib").run();
10
11 // Verify the output is a valid wasm file with a dylink.0 section
12 let file = rfs::read("foo.wasm");
13 let mut has_dylink = false;
14
15 for payload in wasmparser::Parser::new(0).parse_all(&file) {
16 let payload = payload.unwrap();
17 if let wasmparser::Payload::CustomSection(s) = payload {
18 if s.name() == "dylink.0" {
19 has_dylink = true;
20 }
21 }
22 }
23
24 assert!(has_dylink, "expected dylink.0 section in emscripten cdylib output");
25}
tests/ui/async-await/issue-70818.rs+1-2
......@@ -2,9 +2,8 @@
22
33use std::future::Future;
44fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
5 //~^ ERROR future cannot be sent between threads safely
5 //~^ ERROR: future cannot be sent between threads safely
66 async { (ty, ty1) }
7 //~^ ERROR future cannot be sent between threads safely
87}
98
109fn main() {}
tests/ui/async-await/issue-70818.stderr+1-22
......@@ -1,24 +1,3 @@
1error: future cannot be sent between threads safely
2 --> $DIR/issue-70818.rs:6:5
3 |
4LL | async { (ty, ty1) }
5 | ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
6 |
7note: captured value is not `Send`
8 --> $DIR/issue-70818.rs:6:18
9 |
10LL | async { (ty, ty1) }
11 | ^^^ has type `U` which is not `Send`
12note: required by a bound in an opaque type
13 --> $DIR/issue-70818.rs:4:69
14 |
15LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
16 | ^^^^
17help: consider restricting type parameter `U` with trait `Send`
18 |
19LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
20 | +++++++++++++++++++
21
221error: future cannot be sent between threads safely
232 --> $DIR/issue-70818.rs:4:38
243 |
......@@ -35,5 +14,5 @@ help: consider restricting type parameter `U` with trait `Send`
3514LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
3615 | +++++++++++++++++++
3716
38error: aborting due to 2 previous errors
17error: aborting due to 1 previous error
3918
tests/ui/async-await/issue-70935-complex-spans.rs-1
......@@ -15,7 +15,6 @@ async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
1515fn foo(x: NotSync) -> impl Future + Send {
1616 //~^ ERROR `*mut ()` cannot be shared between threads safely
1717 async move {
18 //~^ ERROR `*mut ()` cannot be shared between threads safely
1918 baz(|| async {
2019 foo(x.clone());
2120 }).await;
tests/ui/async-await/issue-70935-complex-spans.stderr+2-45
......@@ -1,46 +1,3 @@
1error[E0277]: `*mut ()` cannot be shared between threads safely
2 --> $DIR/issue-70935-complex-spans.rs:17:5
3 |
4LL | / async move {
5LL | |
6LL | | baz(|| async {
7LL | | foo(x.clone());
8LL | | }).await;
9LL | | }
10 | |_____^ `*mut ()` cannot be shared between threads safely
11 |
12 = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`
13note: required because it appears within the type `PhantomData<*mut ()>`
14 --> $SRC_DIR/core/src/marker.rs:LL:COL
15note: required because it appears within the type `NotSync`
16 --> $DIR/issue-70935-complex-spans.rs:9:8
17 |
18LL | struct NotSync(PhantomData<*mut ()>);
19 | ^^^^^^^
20 = note: required for `&NotSync` to implement `Send`
21note: required because it's used within this closure
22 --> $DIR/issue-70935-complex-spans.rs:19:13
23 |
24LL | baz(|| async {
25 | ^^
26note: required because it's used within this `async` fn body
27 --> $DIR/issue-70935-complex-spans.rs:12:67
28 |
29LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
30 | ___________________________________________________________________^
31LL | | }
32 | |_^
33note: required because it's used within this `async` block
34 --> $DIR/issue-70935-complex-spans.rs:17:5
35 |
36LL | async move {
37 | ^^^^^^^^^^
38note: required by a bound in an opaque type
39 --> $DIR/issue-70935-complex-spans.rs:15:37
40 |
41LL | fn foo(x: NotSync) -> impl Future + Send {
42 | ^^^^
43
441error[E0277]: `*mut ()` cannot be shared between threads safely
452 --> $DIR/issue-70935-complex-spans.rs:15:23
463 |
......@@ -57,7 +14,7 @@ LL | struct NotSync(PhantomData<*mut ()>);
5714 | ^^^^^^^
5815 = note: required for `&NotSync` to implement `Send`
5916note: required because it's used within this closure
60 --> $DIR/issue-70935-complex-spans.rs:19:13
17 --> $DIR/issue-70935-complex-spans.rs:18:13
6118 |
6219LL | baz(|| async {
6320 | ^^
......@@ -74,6 +31,6 @@ note: required because it's used within this `async` block
7431LL | async move {
7532 | ^^^^^^^^^^
7633
77error: aborting due to 2 previous errors
34error: aborting due to 1 previous error
7835
7936For more information about this error, try `rustc --explain E0277`.
tests/ui/coercion/vtable-impossible-predicates-async.rs created+45
......@@ -0,0 +1,45 @@
1// Regression test for #135470.
2// Verify that we don't ICE when building vtable entries
3// for a blanket impl involving async and impossible predicates.
4
5//@ check-pass
6//@ compile-flags: -Copt-level=0
7//@ edition: 2021
8
9use std::future::Future;
10trait Access {
11 type Lister;
12
13 fn list() -> impl Future<Output = Self::Lister> {
14 async { todo!() }
15 }
16}
17
18trait Foo {}
19impl Access for dyn Foo {
20 type Lister = ();
21}
22
23fn main() {
24 let svc = async {
25 async { <dyn Foo>::list() }.await;
26 };
27 &svc as &dyn Service;
28}
29
30trait UnaryService {
31 fn call2() {}
32}
33trait Unimplemented {}
34impl<T: Unimplemented> UnaryService for T {}
35struct Wrap<T>(T);
36impl<T: Send> UnaryService for Wrap<T> {}
37
38trait Service {
39 fn call(&self);
40}
41impl<T: Send> Service for T {
42 fn call(&self) {
43 Wrap::<T>::call2();
44 }
45}
tests/ui/coercion/vtable-unsatisfied-supertrait-generics.rs created+25
......@@ -0,0 +1,25 @@
1// Regression test for #137190.
2// Variant of vtable-unsatisfied-supertrait.rs with generic traits.
3// Verify that we don't ICE when building vtable entries
4// for a generic trait whose supertrait is not implemented.
5
6//@ compile-flags: --crate-type lib
7
8trait Supertrait<T> {
9 fn method(&self) {}
10}
11
12trait Trait<P>: Supertrait<()> {}
13
14impl<P> Trait<P> for () {}
15//~^ ERROR the trait bound `(): Supertrait<()>` is not satisfied
16
17const fn upcast<P>(x: &dyn Trait<P>) -> &dyn Supertrait<()> {
18 x
19}
20
21const fn foo() -> &'static dyn Supertrait<()> {
22 upcast::<()>(&())
23}
24
25const _: &'static dyn Supertrait<()> = foo();
tests/ui/coercion/vtable-unsatisfied-supertrait-generics.stderr created+20
......@@ -0,0 +1,20 @@
1error[E0277]: the trait bound `(): Supertrait<()>` is not satisfied
2 --> $DIR/vtable-unsatisfied-supertrait-generics.rs:14:22
3 |
4LL | impl<P> Trait<P> for () {}
5 | ^^ the trait `Supertrait<()>` is not implemented for `()`
6 |
7help: this trait has no implementations, consider adding one
8 --> $DIR/vtable-unsatisfied-supertrait-generics.rs:8:1
9 |
10LL | trait Supertrait<T> {
11 | ^^^^^^^^^^^^^^^^^^^
12note: required by a bound in `Trait`
13 --> $DIR/vtable-unsatisfied-supertrait-generics.rs:12:17
14 |
15LL | trait Trait<P>: Supertrait<()> {}
16 | ^^^^^^^^^^^^^^ required by this bound in `Trait`
17
18error: aborting due to 1 previous error
19
20For more information about this error, try `rustc --explain E0277`.
tests/ui/coercion/vtable-unsatisfied-supertrait.rs created+16
......@@ -0,0 +1,16 @@
1// Regression test for #137190.
2// Verify that we don't ICE when building vtable entries
3// for a trait whose supertrait is not implemented.
4
5//@ compile-flags: --crate-type lib
6
7trait Supertrait {
8 fn method(&self) {}
9}
10
11trait Trait: Supertrait {}
12
13impl Trait for () {}
14//~^ ERROR the trait bound `(): Supertrait` is not satisfied
15
16const _: &dyn Supertrait = &() as &dyn Trait as &dyn Supertrait;
tests/ui/coercion/vtable-unsatisfied-supertrait.stderr created+20
......@@ -0,0 +1,20 @@
1error[E0277]: the trait bound `(): Supertrait` is not satisfied
2 --> $DIR/vtable-unsatisfied-supertrait.rs:13:16
3 |
4LL | impl Trait for () {}
5 | ^^ the trait `Supertrait` is not implemented for `()`
6 |
7help: this trait has no implementations, consider adding one
8 --> $DIR/vtable-unsatisfied-supertrait.rs:7:1
9 |
10LL | trait Supertrait {
11 | ^^^^^^^^^^^^^^^^
12note: required by a bound in `Trait`
13 --> $DIR/vtable-unsatisfied-supertrait.rs:11:14
14 |
15LL | trait Trait: Supertrait {}
16 | ^^^^^^^^^^ required by this bound in `Trait`
17
18error: aborting due to 1 previous error
19
20For more information about this error, try `rustc --explain E0277`.
tests/ui/coroutine/issue-105084.rs-1
......@@ -36,7 +36,6 @@ fn main() {
3636 // one inside `g` and one inside `h`.
3737 // Proceed and drop `t` in `g`.
3838 Pin::new(&mut g).resume(());
39 //~^ ERROR borrow of moved value: `g`
4039
4140 // Proceed and drop `t` in `h` -> double free!
4241 Pin::new(&mut h).resume(());
tests/ui/coroutine/issue-105084.stderr+2-27
......@@ -1,27 +1,3 @@
1error[E0382]: borrow of moved value: `g`
2 --> $DIR/issue-105084.rs:38:14
3 |
4LL | let mut g = #[coroutine]
5 | ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, which does not implement the `Copy` trait
6...
7LL | let mut h = copy(g);
8 | - value moved here
9...
10LL | Pin::new(&mut g).resume(());
11 | ^^^^^^ value borrowed here after move
12 |
13note: consider changing this parameter type in function `copy` to borrow instead if owning the value isn't necessary
14 --> $DIR/issue-105084.rs:10:21
15 |
16LL | fn copy<T: Copy>(x: T) -> T {
17 | ---- ^ this parameter takes ownership of the value
18 | |
19 | in this function
20help: consider cloning the value if the performance cost is acceptable
21 |
22LL | let mut h = copy(g.clone());
23 | ++++++++
24
251error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`
262 --> $DIR/issue-105084.rs:32:17
273 |
......@@ -45,7 +21,6 @@ note: required by a bound in `copy`
4521LL | fn copy<T: Copy>(x: T) -> T {
4622 | ^^^^ required by this bound in `copy`
4723
48error: aborting due to 2 previous errors
24error: aborting due to 1 previous error
4925
50Some errors have detailed explanations: E0277, E0382.
51For more information about an error, try `rustc --explain E0277`.
26For more information about this error, try `rustc --explain E0277`.
tests/ui/coroutine/stalled-coroutine-obligations.rs created+32
......@@ -0,0 +1,32 @@
1//@ edition: 2021
2
3// Regression tests for #137916 and #138274
4// We now check stalled coroutine obligations eagerly at the start of `mir_borrowck`.
5// So these unsatisfied bounds are caught before causing ICEs.
6use std::ptr::null;
7
8async fn a() -> Box<dyn Send> {
9 Box::new(async {
10 //~^ ERROR: future cannot be sent between threads safely
11 let non_send = null::<()>();
12 &non_send;
13 async {}.await
14 })
15}
16
17
18trait Trait {}
19fn foo() -> Box<dyn Trait> { todo!() }
20
21fn fetch() {
22 async {
23 let fut = async {
24 let _x = foo();
25 async {}.await;
26 };
27 let _: Box<dyn Send> = Box::new(fut);
28 //~^ ERROR: future cannot be sent between threads safely
29 };
30}
31
32fn main() {}
tests/ui/coroutine/stalled-coroutine-obligations.stderr created+40
......@@ -0,0 +1,40 @@
1error: future cannot be sent between threads safely
2 --> $DIR/stalled-coroutine-obligations.rs:9:5
3 |
4LL | / Box::new(async {
5LL | |
6LL | | let non_send = null::<()>();
7LL | | &non_send;
8LL | | async {}.await
9LL | | })
10 | |______^ future created by async block is not `Send`
11 |
12 = help: within `{async block@$DIR/stalled-coroutine-obligations.rs:9:14: 9:19}`, the trait `Send` is not implemented for `*const ()`
13note: future is not `Send` as this value is used across an await
14 --> $DIR/stalled-coroutine-obligations.rs:13:18
15 |
16LL | let non_send = null::<()>();
17 | -------- has type `*const ()` which is not `Send`
18LL | &non_send;
19LL | async {}.await
20 | ^^^^^ await occurs here, with `non_send` maybe used later
21 = note: required for the cast from `Box<{async block@$DIR/stalled-coroutine-obligations.rs:9:14: 9:19}>` to `Box<dyn Send>`
22
23error: future cannot be sent between threads safely
24 --> $DIR/stalled-coroutine-obligations.rs:27:32
25 |
26LL | let _: Box<dyn Send> = Box::new(fut);
27 | ^^^^^^^^^^^^^ future created by async block is not `Send`
28 |
29 = help: the trait `Send` is not implemented for `dyn Trait`
30note: future is not `Send` as this value is used across an await
31 --> $DIR/stalled-coroutine-obligations.rs:25:22
32 |
33LL | let _x = foo();
34 | -- has type `Box<dyn Trait>` which is not `Send`
35LL | async {}.await;
36 | ^^^^^ await occurs here, with `_x` maybe used later
37 = note: required for the cast from `Box<{async block@$DIR/stalled-coroutine-obligations.rs:23:19: 23:24}>` to `Box<dyn Send>`
38
39error: aborting due to 2 previous errors
40
tests/ui/suggestions/issue-71394-no-from-impl.stderr+1-1
......@@ -13,7 +13,7 @@ LL | let _: &[i8] = data.into();
1313 `[T; 6]` implements `From<(T, T, T, T, T, T)>`
1414 `[T; 7]` implements `From<(T, T, T, T, T, T, T)>`
1515 `[T; 8]` implements `From<(T, T, T, T, T, T, T, T)>`
16 and 6 others
16 and 7 others
1717 = note: required for `&[u8]` to implement `Into<&[i8]>`
1818
1919error: aborting due to 1 previous error
tests/ui/traits/next-solver/stalled-coroutine-obligations.rs created+50
......@@ -0,0 +1,50 @@
1//@ edition: 2024
2//@ compile-flags: -Znext-solver --diagnostic-width=300
3
4// Previously we check stalled coroutine obligations after borrowck pass.
5// And we wrongly assume that these obligations hold in borrowck which leads to
6// silent normalization failures.
7// In the next solver, we register opaques types via `NormalizesTo` goals.
8// So these failures also cause those opaques types not registered in storage.
9//
10// Regression test for #151322 and #151323.
11
12#![feature(type_alias_impl_trait)]
13#![feature(negative_impls)]
14#![feature(auto_traits)]
15
16fn stalled_copy_clone() {
17 type T = impl Copy;
18 let foo: T = async {};
19 //~^ ERROR: the trait bound
20
21 type U = impl Clone;
22 let bar: U = async {};
23 //~^ ERROR: the trait bound
24}
25
26auto trait Valid {}
27struct False;
28impl !Valid for False {}
29
30fn stalled_auto_traits() {
31 type T = impl Valid;
32 let a = False;
33 let foo: T = async { a };
34 //~^ ERROR: the trait bound `False: Valid` is not satisfied
35}
36
37
38trait Trait {
39 fn stalled_send(&self, b: *mut ()) -> impl Future + Send {
40 //~^ ERROR: type mismatch resolving
41 //~| ERROR: type mismatch resolving
42 async move {
43 //~^ ERROR: type mismatch resolving
44 b
45 }
46 }
47}
48
49
50fn main() {}
tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr created+62
......@@ -0,0 +1,62 @@
1error[E0277]: the trait bound `{async block@$DIR/stalled-coroutine-obligations.rs:18:18: 18:23}: Copy` is not satisfied
2 --> $DIR/stalled-coroutine-obligations.rs:18:14
3 |
4LL | let foo: T = async {};
5 | ^ the trait `Copy` is not implemented for `{async block@$DIR/stalled-coroutine-obligations.rs:18:18: 18:23}`
6
7error[E0277]: the trait bound `{async block@$DIR/stalled-coroutine-obligations.rs:22:18: 22:23}: Clone` is not satisfied
8 --> $DIR/stalled-coroutine-obligations.rs:22:14
9 |
10LL | let bar: U = async {};
11 | ^ the trait `Clone` is not implemented for `{async block@$DIR/stalled-coroutine-obligations.rs:22:18: 22:23}`
12
13error[E0277]: the trait bound `False: Valid` is not satisfied in `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}`
14 --> $DIR/stalled-coroutine-obligations.rs:33:14
15 |
16LL | let foo: T = async { a };
17 | ^ ----- within this `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}`
18 | |
19 | unsatisfied trait bound
20 |
21help: within `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}`, the trait `Valid` is not implemented for `False`
22 --> $DIR/stalled-coroutine-obligations.rs:27:1
23 |
24LL | struct False;
25 | ^^^^^^^^^^^^
26note: captured value does not implement `Valid`
27 --> $DIR/stalled-coroutine-obligations.rs:33:26
28 |
29LL | let foo: T = async { a };
30 | ^ has type `False` which does not implement `Valid`
31
32error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}`
33 --> $DIR/stalled-coroutine-obligations.rs:39:5
34 |
35LL | fn stalled_send(&self, b: *mut ()) -> impl Future + Send {
36 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
37
38error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}`
39 --> $DIR/stalled-coroutine-obligations.rs:42:9
40 |
41LL | / async move {
42LL | |
43LL | | b
44LL | | }
45 | |_________^ types differ
46
47error[E0271]: type mismatch resolving `{async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19} <: impl Future + Send`
48 --> $DIR/stalled-coroutine-obligations.rs:39:62
49 |
50LL | fn stalled_send(&self, b: *mut ()) -> impl Future + Send {
51 | ______________________________________________________________^
52LL | |
53LL | |
54LL | | async move {
55... |
56LL | | }
57 | |_____^ types differ
58
59error: aborting due to 6 previous errors
60
61Some errors have detailed explanations: E0271, E0277.
62For more information about an error, try `rustc --explain E0271`.