Skip to content

Commit 339ae32

Browse files
authored
Merge branch 'rust-lang:master' into rtems-add-getentropy
2 parents 89c795f + db8043b commit 339ae32

File tree

544 files changed

+6869
-4158
lines changed

Some content is hidden

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

544 files changed

+6869
-4158
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ build/
5757
/src/tools/x/target
5858
# Created by default with `src/ci/docker/run.sh`
5959
/obj/
60+
# Created by nix dev shell / .envrc
61+
src/tools/nix-dev-shell/flake.lock
6062

6163
## ICE reports
6264
rustc-ice-*.txt

.mailmap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com>
256256
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub.bukaj@yahoo.com>
257257
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub@jakub.cc>
258258
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakubw@jakubw.net>
259+
Jakub Beránek <berykubik@gmail.com> <jakub.beranek@vsb.cz>
259260
James [Undefined] <tpzker@thepuzzlemaker.info>
260261
James Deng <cnjamesdeng@gmail.com> <cnJamesDeng@gmail.com>
261262
James Hinshelwood <jameshinshelwood1@gmail.com> <james.hinshelwood@bigpayme.com>
@@ -280,6 +281,7 @@ Jerry Hardee <hardeejj9@gmail.com>
280281
Jesús Rubio <jesusprubio@gmail.com>
281282
Jethro Beekman <github@jbeekman.nl>
282283
Jian Zeng <knight42@mail.ustc.edu.cn>
284+
Jieyou Xu <jieyouxu@outlook.com> <39484203+jieyouxu@users.noreply.github.com>
283285
Jihyun Yu <j.yu@navercorp.com> <yjh0502@gmail.com>
284286
Jihyun Yu <j.yu@navercorp.com> jihyun <jihyun@nablecomm.com>
285287
Jihyun Yu <j.yu@navercorp.com> Jihyun Yu <jihyun@nclab.kaist.ac.kr>

RELEASES.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ Stabilized APIs
123123
These APIs are now stable in const contexts:
124124

125125
- [`std::task::Waker::from_raw`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw)
126-
- [`std::task::Waker::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw)
127126
- [`std::task::Context::from_waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.from_waker)
128127
- [`std::task::Context::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.waker)
129128
- [`$integer::from_str_radix`](https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.from_str_radix)

compiler/rustc_attr/src/builtin.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,13 @@ pub fn eval_condition(
723723
}
724724

725725
mis.iter().fold(true, |res, mi| {
726-
let mut mi = mi.meta_item().unwrap().clone();
726+
let Some(mut mi) = mi.meta_item().cloned() else {
727+
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier {
728+
span: mi.span(),
729+
});
730+
return false;
731+
};
732+
727733
if let [seg, ..] = &mut mi.path.segments[..] {
728734
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
729735
}

compiler/rustc_borrowck/src/dataflow.rs

Lines changed: 25 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
use rustc_data_structures::fx::FxIndexMap;
22
use rustc_data_structures::graph;
33
use rustc_index::bit_set::BitSet;
4-
use rustc_middle::mir::{
5-
self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges,
6-
};
4+
use rustc_middle::mir::{self, BasicBlock, Body, Location, Place, TerminatorEdges};
75
use rustc_middle::ty::{RegionVid, TyCtxt};
86
use rustc_mir_dataflow::fmt::DebugWithContext;
97
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
10-
use rustc_mir_dataflow::{Analysis, AnalysisDomain, Forward, GenKill, Results, ResultsVisitable};
8+
use rustc_mir_dataflow::{Analysis, Forward, GenKill, Results, ResultsVisitable};
119
use tracing::debug;
1210

1311
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict};
@@ -22,9 +20,9 @@ pub(crate) struct BorrowckResults<'a, 'tcx> {
2220
/// The transient state of the dataflow analyses used by the borrow checker.
2321
#[derive(Debug)]
2422
pub(crate) struct BorrowckDomain<'a, 'tcx> {
25-
pub(crate) borrows: <Borrows<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
26-
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
27-
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
23+
pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain,
24+
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
25+
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
2826
}
2927

3028
impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> {
@@ -427,7 +425,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
427425
/// That means they went out of a nonlexical scope
428426
fn kill_loans_out_of_scope_at_location(
429427
&self,
430-
trans: &mut impl GenKill<BorrowIndex>,
428+
trans: &mut <Self as Analysis<'tcx>>::Domain,
431429
location: Location,
432430
) {
433431
// NOTE: The state associated with a given `location`
@@ -447,7 +445,11 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
447445
}
448446

449447
/// Kill any borrows that conflict with `place`.
450-
fn kill_borrows_on_place(&self, trans: &mut impl GenKill<BorrowIndex>, place: Place<'tcx>) {
448+
fn kill_borrows_on_place(
449+
&self,
450+
trans: &mut <Self as Analysis<'tcx>>::Domain,
451+
place: Place<'tcx>,
452+
) {
451453
debug!("kill_borrows_on_place: place={:?}", place);
452454

453455
let other_borrows_of_local = self
@@ -486,7 +488,14 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
486488
}
487489
}
488490

489-
impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
491+
/// Forward dataflow computation of the set of borrows that are in scope at a particular location.
492+
/// - we gen the introduced loans
493+
/// - we kill loans on locals going out of (regular) scope
494+
/// - we kill the loans going out of their region's NLL scope: in NLL terms, the frontier where a
495+
/// region stops containing the CFG points reachable from the issuing location.
496+
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
497+
/// `a.b.c` when `a` is overwritten.
498+
impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
490499
type Domain = BitSet<BorrowIndex>;
491500

492501
const NAME: &'static str = "borrows";
@@ -500,34 +509,19 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
500509
// no borrows of code region_scopes have been taken prior to
501510
// function execution, so this method has no effect.
502511
}
503-
}
504-
505-
/// Forward dataflow computation of the set of borrows that are in scope at a particular location.
506-
/// - we gen the introduced loans
507-
/// - we kill loans on locals going out of (regular) scope
508-
/// - we kill the loans going out of their region's NLL scope: in NLL terms, the frontier where a
509-
/// region stops containing the CFG points reachable from the issuing location.
510-
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
511-
/// `a.b.c` when `a` is overwritten.
512-
impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
513-
type Idx = BorrowIndex;
514-
515-
fn domain_size(&self, _: &mir::Body<'tcx>) -> usize {
516-
self.borrow_set.len()
517-
}
518512

519-
fn before_statement_effect(
513+
fn apply_before_statement_effect(
520514
&mut self,
521-
trans: &mut impl GenKill<Self::Idx>,
515+
trans: &mut Self::Domain,
522516
_statement: &mir::Statement<'tcx>,
523517
location: Location,
524518
) {
525519
self.kill_loans_out_of_scope_at_location(trans, location);
526520
}
527521

528-
fn statement_effect(
522+
fn apply_statement_effect(
529523
&mut self,
530-
trans: &mut impl GenKill<Self::Idx>,
524+
trans: &mut Self::Domain,
531525
stmt: &mir::Statement<'tcx>,
532526
location: Location,
533527
) {
@@ -573,7 +567,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
573567
}
574568
}
575569

576-
fn before_terminator_effect(
570+
fn apply_before_terminator_effect(
577571
&mut self,
578572
trans: &mut Self::Domain,
579573
_terminator: &mir::Terminator<'tcx>,
@@ -582,7 +576,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
582576
self.kill_loans_out_of_scope_at_location(trans, location);
583577
}
584578

585-
fn terminator_effect<'mir>(
579+
fn apply_terminator_effect<'mir>(
586580
&mut self,
587581
trans: &mut Self::Domain,
588582
terminator: &'mir mir::Terminator<'tcx>,
@@ -599,14 +593,6 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
599593
}
600594
terminator.edges()
601595
}
602-
603-
fn call_return_effect(
604-
&mut self,
605-
_trans: &mut Self::Domain,
606-
_block: mir::BasicBlock,
607-
_return_places: CallReturnPlaces<'_, 'tcx>,
608-
) {
609-
}
610596
}
611597

612598
impl<C> DebugWithContext<C> for BorrowIndex {}

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ use std::rc::Rc;
33

44
use rustc_errors::Diag;
55
use rustc_hir::def_id::LocalDefId;
6-
use rustc_infer::infer::canonical::Canonical;
6+
use rustc_infer::infer::canonical::CanonicalQueryInput;
77
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
88
use rustc_infer::infer::{
99
InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt as _,
1010
};
1111
use rustc_infer::traits::ObligationCause;
12+
use rustc_infer::traits::query::{
13+
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
14+
CanonicalTypeOpProvePredicateGoal,
15+
};
1216
use rustc_middle::ty::error::TypeError;
1317
use rustc_middle::ty::{
1418
self, RePlaceholder, Region, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex,
@@ -95,9 +99,7 @@ impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tc
9599
}
96100
}
97101

98-
impl<'tcx> ToUniverseInfo<'tcx>
99-
for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
100-
{
102+
impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpProvePredicateGoal<'tcx> {
101103
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
102104
UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery {
103105
canonical_query: self,
@@ -107,7 +109,7 @@ impl<'tcx> ToUniverseInfo<'tcx>
107109
}
108110

109111
impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUniverseInfo<'tcx>
110-
for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>
112+
for CanonicalTypeOpNormalizeGoal<'tcx, T>
111113
{
112114
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
113115
UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery {
@@ -117,9 +119,7 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUnivers
117119
}
118120
}
119121

120-
impl<'tcx> ToUniverseInfo<'tcx>
121-
for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>
122-
{
122+
impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> {
123123
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
124124
UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(AscribeUserTypeQuery {
125125
canonical_query: self,
@@ -128,7 +128,7 @@ impl<'tcx> ToUniverseInfo<'tcx>
128128
}
129129
}
130130

131-
impl<'tcx, F> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F>> {
131+
impl<'tcx, F> ToUniverseInfo<'tcx> for CanonicalQueryInput<'tcx, type_op::custom::CustomTypeOp<F>> {
132132
fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
133133
// We can't rerun custom type ops.
134134
UniverseInfo::other()
@@ -211,16 +211,15 @@ trait TypeOpInfo<'tcx> {
211211
}
212212

213213
struct PredicateQuery<'tcx> {
214-
canonical_query:
215-
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>,
214+
canonical_query: CanonicalTypeOpProvePredicateGoal<'tcx>,
216215
base_universe: ty::UniverseIndex,
217216
}
218217

219218
impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
220219
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> {
221220
tcx.dcx().create_err(HigherRankedLifetimeError {
222221
cause: Some(HigherRankedErrorCause::CouldNotProve {
223-
predicate: self.canonical_query.value.value.predicate.to_string(),
222+
predicate: self.canonical_query.canonical.value.value.predicate.to_string(),
224223
}),
225224
span,
226225
})
@@ -253,7 +252,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
253252
}
254253

255254
struct NormalizeQuery<'tcx, T> {
256-
canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>,
255+
canonical_query: CanonicalTypeOpNormalizeGoal<'tcx, T>,
257256
base_universe: ty::UniverseIndex,
258257
}
259258

@@ -264,7 +263,7 @@ where
264263
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> {
265264
tcx.dcx().create_err(HigherRankedLifetimeError {
266265
cause: Some(HigherRankedErrorCause::CouldNotNormalize {
267-
value: self.canonical_query.value.value.value.to_string(),
266+
value: self.canonical_query.canonical.value.value.value.to_string(),
268267
}),
269268
span,
270269
})
@@ -306,7 +305,7 @@ where
306305
}
307306

308307
struct AscribeUserTypeQuery<'tcx> {
309-
canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>,
308+
canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
310309
base_universe: ty::UniverseIndex,
311310
}
312311

compiler/rustc_borrowck/src/type_check/canonical.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
137137
let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
138138
locations,
139139
category,
140-
param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
140+
param_env.and(type_op::prove_predicate::ProvePredicate { predicate }),
141141
);
142142
}
143143

@@ -162,7 +162,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
162162
let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
163163
location.to_locations(),
164164
category,
165-
param_env.and(type_op::normalize::Normalize::new(value)),
165+
param_env.and(type_op::normalize::Normalize { value }),
166166
);
167167
result.unwrap_or(value)
168168
}
@@ -223,7 +223,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
223223
let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
224224
Locations::All(span),
225225
ConstraintCategory::Boring,
226-
self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)),
226+
self.param_env.and(type_op::ascribe_user_type::AscribeUserType { mir_ty, user_ty }),
227227
);
228228
}
229229

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
280280
}
281281
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
282282
.param_env
283-
.and(type_op::normalize::Normalize::new(ty))
283+
.and(type_op::normalize::Normalize { value: ty })
284284
.fully_perform(self.infcx, span)
285285
.unwrap_or_else(|guar| TypeOpOutput {
286286
output: Ty::new_error(self.infcx.tcx, guar),
@@ -318,7 +318,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
318318
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
319319
let result: Result<_, ErrorGuaranteed> = self
320320
.param_env
321-
.and(type_op::normalize::Normalize::new(ty))
321+
.and(type_op::normalize::Normalize { value: ty })
322322
.fully_perform(self.infcx, span);
323323
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
324324
continue;
@@ -373,7 +373,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
373373
) -> Option<&'tcx QueryRegionConstraints<'tcx>> {
374374
let TypeOpOutput { output: bounds, constraints, .. } = self
375375
.param_env
376-
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
376+
.and(type_op::ImpliedOutlivesBounds { ty })
377377
.fully_perform(self.infcx, span)
378378
.map_err(|_: ErrorGuaranteed| debug!("failed to compute implied bounds {:?}", ty))
379379
.ok()?;

compiler/rustc_borrowck/src/type_check/liveness/trace.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
1111
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
1212
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
1313
use rustc_span::DUMMY_SP;
14-
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
15-
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
14+
use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput};
1615
use tracing::debug;
1716

1817
use crate::location::RichLocation;
@@ -632,7 +631,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
632631

633632
match typeck
634633
.param_env
635-
.and(DropckOutlives::new(dropped_ty))
634+
.and(DropckOutlives { dropped_ty })
636635
.fully_perform(typeck.infcx, DUMMY_SP)
637636
{
638637
Ok(TypeOpOutput { output, constraints, .. }) => {

compiler/rustc_codegen_cranelift/src/unsize.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ pub(crate) fn unsized_info<'tcx>(
3434
{
3535
let old_info =
3636
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
37-
if data_a.principal_def_id() == data_b.principal_def_id() {
37+
let b_principal_def_id = data_b.principal_def_id();
38+
if data_a.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
39+
// A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
3840
debug_assert!(
3941
validate_trivial_unsize(fx.tcx, data_a, data_b),
4042
"NOP unsize vtable changed principal trait ref: {data_a} -> {data_b}"

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,16 @@ pub(crate) unsafe fn create_module<'ll>(
138138
}
139139
}
140140

141+
if llvm_version < (20, 0, 0) {
142+
if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") {
143+
// LLVM 20 defines three additional address spaces for alternate
144+
// pointer kinds used in Windows.
145+
// See https://github.com/llvm/llvm-project/pull/111879
146+
target_data_layout =
147+
target_data_layout.replace("-p270:32:32-p271:32:32-p272:64:64", "");
148+
}
149+
}
150+
141151
// Ensure the data-layout values hardcoded remain the defaults.
142152
{
143153
let tm = crate::back::write::create_informational_target_machine(tcx.sess, false);

0 commit comments

Comments
 (0)