diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 6edc3d926b85586eeda01f816ced9eaa0edadd7d..a65b52968a59c4c0b69b2f9ab09694635169962c 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -2382,9 +2382,8 @@ JumbleRangeTable(pgssJumbleState *jstate, List *rtable)
 
 	foreach(lc, rtable)
 	{
-		RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
+		RangeTblEntry *rte = castNode(RangeTblEntry, lfirst(lc));
 
-		Assert(IsA(rte, RangeTblEntry));
 		APP_JUMB(rte->rtekind);
 		switch (rte->rtekind)
 		{
@@ -2570,7 +2569,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
 				APP_JUMB(sublink->subLinkType);
 				APP_JUMB(sublink->subLinkId);
 				JumbleExpr(jstate, (Node *) sublink->testexpr);
-				JumbleQuery(jstate, (Query *) sublink->subselect);
+				JumbleQuery(jstate, castNode(Query, sublink->subselect));
 			}
 			break;
 		case T_FieldSelect:
@@ -2636,9 +2635,8 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
 				JumbleExpr(jstate, (Node *) caseexpr->arg);
 				foreach(temp, caseexpr->args)
 				{
-					CaseWhen   *when = (CaseWhen *) lfirst(temp);
+					CaseWhen   *when = castNode(CaseWhen, lfirst(temp));
 
-					Assert(IsA(when, CaseWhen));
 					JumbleExpr(jstate, (Node *) when->expr);
 					JumbleExpr(jstate, (Node *) when->result);
 				}
@@ -2850,7 +2848,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
 
 				/* we store the string name because RTE_CTE RTEs need it */
 				APP_JUMB_STRING(cte->ctename);
-				JumbleQuery(jstate, (Query *) cte->ctequery);
+				JumbleQuery(jstate, castNode(Query, cte->ctequery));
 			}
 			break;
 		case T_SetOperationStmt:
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index 6bdeda9824089d1a6f38323b5f91d2b5ec1ca3d5..d2b94aaf3bafd47b8551cb0bcbbddb83d31ecd79 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -1315,10 +1315,7 @@ deparseExplicitTargetList(List *tlist, List **retrieved_attrs,
 
 	foreach(lc, tlist)
 	{
-		TargetEntry *tle = (TargetEntry *) lfirst(lc);
-
-		/* Extract expression if TargetEntry node */
-		Assert(IsA(tle, TargetEntry));
+		TargetEntry *tle = castNode(TargetEntry, lfirst(lc));
 
 		if (i > 0)
 			appendStringInfoString(buf, ", ");
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index ce1f443d55564bc09fb9aff08b3084c697830f7f..f396a227f7e66b7c67095b91c619eee3cdb342dc 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -1159,9 +1159,7 @@ postgresGetForeignPlan(PlannerInfo *root,
 	 */
 	foreach(lc, scan_clauses)
 	{
-		RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
-
-		Assert(IsA(rinfo, RestrictInfo));
+		RestrictInfo *rinfo = castNode(RestrictInfo, lfirst(lc));
 
 		/* Ignore any pseudoconstants, they're dealt with elsewhere */
 		if (rinfo->pseudoconstant)
@@ -4958,14 +4956,12 @@ conversion_error_callback(void *arg)
 	{
 		/* error occurred in a scan against a foreign join */
 		ForeignScanState *fsstate = errpos->fsstate;
-		ForeignScan *fsplan = (ForeignScan *) fsstate->ss.ps.plan;
+		ForeignScan *fsplan = castNode(ForeignScan, fsstate->ss.ps.plan);
 		EState	   *estate = fsstate->ss.ps.state;
 		TargetEntry *tle;
 
-		Assert(IsA(fsplan, ForeignScan));
-		tle = (TargetEntry *) list_nth(fsplan->fdw_scan_tlist,
-									   errpos->cur_attno - 1);
-		Assert(IsA(tle, TargetEntry));
+		tle = castNode(TargetEntry, list_nth(fsplan->fdw_scan_tlist,
+											 errpos->cur_attno - 1));
 
 		/*
 		 * Target list can have Vars and expressions.  For Vars, we can get
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 7ae192a40742ae8705b95a06c7326e59ceef57dd..bb83a9a7c6e52a894f287678a3ad1eabec91c75c 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -510,8 +510,7 @@ ProcedureCreate(const char *procedureName,
 											 Anum_pg_proc_proargdefaults,
 											 &isnull);
 			Assert(!isnull);
-			oldDefaults = (List *) stringToNode(TextDatumGetCString(proargdefaults));
-			Assert(IsA(oldDefaults, List));
+			oldDefaults = castNode(List, stringToNode(TextDatumGetCString(proargdefaults)));
 			Assert(list_length(oldDefaults) == oldproc->pronargdefaults);
 
 			/* new list can have more defaults than old, advance over 'em */
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 02ea254cd498f02d7ac0a47f3a0b5b57d50183bb..23411293518abe87064ef5febb8193a67c731199 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -109,13 +109,13 @@ DefineAggregate(ParseState *pstate, List *name, List *args, bool oldstyle, List
 			aggKind = AGGKIND_ORDERED_SET;
 		else
 			numDirectArgs = 0;
-		args = (List *) linitial(args);
+		args = castNode(List, linitial(args));
 	}
 
 	/* Examine aggregate's definition clauses */
 	foreach(pl, parameters)
 	{
-		DefElem    *defel = (DefElem *) lfirst(pl);
+		DefElem    *defel = castNode(DefElem, lfirst(pl));
 
 		/*
 		 * sfunc1, stype1, and initcond1 are accepted as obsolete spellings
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index e3e1a5307277a34f790b536c71bdc69e8b352490..c9f6afeb1aa4a1cf9fa34df102348d059e9a908b 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -722,9 +722,9 @@ compute_index_stats(Relation onerel, double totalrows,
 		econtext->ecxt_scantuple = slot;
 
 		/* Set up execution state for predicate. */
-		predicate = (List *)
-			ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
-							estate);
+		predicate = castNode(List,
+							 ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
+											 estate));
 
 		/* Compute and save index expression values */
 		exprvals = (Datum *) palloc(numrows * attr_cnt * sizeof(Datum));
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 6d0ce7a3580cb36cef22a3d3e7a36c9137e3173f..e32d7a1d4ec5dae658a60a2b00884264fc6c73b9 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -1636,7 +1636,7 @@ AtSubCommit_Notify(void)
 	List	   *parentPendingActions;
 	List	   *parentPendingNotifies;
 
-	parentPendingActions = (List *) linitial(upperPendingActions);
+	parentPendingActions = castNode(List, linitial(upperPendingActions));
 	upperPendingActions = list_delete_first(upperPendingActions);
 
 	Assert(list_length(upperPendingActions) ==
@@ -1647,7 +1647,7 @@ AtSubCommit_Notify(void)
 	 */
 	pendingActions = list_concat(parentPendingActions, pendingActions);
 
-	parentPendingNotifies = (List *) linitial(upperPendingNotifies);
+	parentPendingNotifies = castNode(List, linitial(upperPendingNotifies));
 	upperPendingNotifies = list_delete_first(upperPendingNotifies);
 
 	Assert(list_length(upperPendingNotifies) ==
@@ -1679,13 +1679,13 @@ AtSubAbort_Notify(void)
 	 */
 	while (list_length(upperPendingActions) > my_level - 2)
 	{
-		pendingActions = (List *) linitial(upperPendingActions);
+		pendingActions = castNode(List, linitial(upperPendingActions));
 		upperPendingActions = list_delete_first(upperPendingActions);
 	}
 
 	while (list_length(upperPendingNotifies) > my_level - 2)
 	{
-		pendingNotifies = (List *) linitial(upperPendingNotifies);
+		pendingNotifies = castNode(List, linitial(upperPendingNotifies));
 		upperPendingNotifies = list_delete_first(upperPendingNotifies);
 	}
 }
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index 8d4d5b7b63bb2c56cce41f6d27d07ba402097ea9..e165d4b2a6b2c57c09256416a5674c2ece6031b3 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -61,7 +61,7 @@ DefineCollation(ParseState *pstate, List *names, List *parameters)
 
 	foreach(pl, parameters)
 	{
-		DefElem    *defel = (DefElem *) lfirst(pl);
+		DefElem    *defel = castNode(DefElem, lfirst(pl));
 		DefElem   **defelp;
 
 		if (pg_strcasecmp(defel->defname, "from") == 0)
diff --git a/src/backend/commands/constraint.c b/src/backend/commands/constraint.c
index 77cf8ceee7687204501a8f108dbde0b018dca32b..e9eeacd03a9ef39287d1ff0bfe47f5a2683ab251 100644
--- a/src/backend/commands/constraint.c
+++ b/src/backend/commands/constraint.c
@@ -37,7 +37,7 @@
 Datum
 unique_key_recheck(PG_FUNCTION_ARGS)
 {
-	TriggerData *trigdata = (TriggerData *) fcinfo->context;
+	TriggerData *trigdata = castNode(TriggerData, fcinfo->context);
 	const char *funcname = "unique_key_recheck";
 	HeapTuple	new_row;
 	ItemPointerData tmptid;
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index f9362be031a74543b927559c460ce4765851697f..949844d979108433f8e92527ff16646017230a61 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -1026,7 +1026,7 @@ ProcessCopyOptions(ParseState *pstate,
 	/* Extract options from the statement node tree */
 	foreach(option, options)
 	{
-		DefElem    *defel = (DefElem *) lfirst(option);
+		DefElem    *defel = castNode(DefElem, lfirst(option));
 
 		if (strcmp(defel->defname, "format") == 0)
 		{
@@ -1139,7 +1139,7 @@ ProcessCopyOptions(ParseState *pstate,
 						 errmsg("conflicting or redundant options"),
 						 parser_errposition(pstate, defel->location)));
 			if (defel->arg && IsA(defel->arg, List))
-				cstate->force_notnull = (List *) defel->arg;
+				cstate->force_notnull = castNode(List, defel->arg);
 			else
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1154,7 +1154,7 @@ ProcessCopyOptions(ParseState *pstate,
 						(errcode(ERRCODE_SYNTAX_ERROR),
 						 errmsg("conflicting or redundant options")));
 			if (defel->arg && IsA(defel->arg, List))
-				cstate->force_null = (List *) defel->arg;
+				cstate->force_null = castNode(List, defel->arg);
 			else
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1176,7 +1176,7 @@ ProcessCopyOptions(ParseState *pstate,
 						 parser_errposition(pstate, defel->location)));
 			cstate->convert_selectively = true;
 			if (defel->arg == NULL || IsA(defel->arg, List))
-				cstate->convert_select = (List *) defel->arg;
+				cstate->convert_select = castNode(List, defel->arg);
 			else
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1479,7 +1479,7 @@ BeginCopy(ParseState *pstate,
 			/* examine queries to determine which error message to issue */
 			foreach(lc, rewritten)
 			{
-				Query	   *q = (Query *) lfirst(lc);
+				Query	   *q = castNode(Query, lfirst(lc));
 
 				if (q->querySource == QSRC_QUAL_INSTEAD_RULE)
 					ereport(ERROR,
@@ -1496,7 +1496,7 @@ BeginCopy(ParseState *pstate,
 					 errmsg("multi-statement DO INSTEAD rules are not supported for COPY")));
 		}
 
-		query = (Query *) linitial(rewritten);
+		query = castNode(Query, linitial(rewritten));
 
 		/* The grammar allows SELECT INTO, but we don't support that */
 		if (query->utilityStmt != NULL &&
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index cee3b4d50b5d5a906c24c000eec005bcd7ed202c..02cfcd182d01a0c728257156d5fd9d28f296afb5 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -224,7 +224,7 @@ ObjectAddress
 ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
 				  ParamListInfo params, char *completionTag)
 {
-	Query	   *query = (Query *) stmt->query;
+	Query	   *query = castNode(Query, stmt->query);
 	IntoClause *into = stmt->into;
 	bool		is_matview = (into->viewQuery != NULL);
 	DestReceiver *dest;
@@ -261,11 +261,10 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
 	 * The contained Query could be a SELECT, or an EXECUTE utility command.
 	 * If the latter, we just pass it off to ExecuteQuery.
 	 */
-	Assert(IsA(query, Query));
 	if (query->commandType == CMD_UTILITY &&
 		IsA(query->utilityStmt, ExecuteStmt))
 	{
-		ExecuteStmt *estmt = (ExecuteStmt *) query->utilityStmt;
+		ExecuteStmt *estmt = castNode(ExecuteStmt, query->utilityStmt);
 
 		Assert(!is_matview);	/* excluded by syntax */
 		ExecuteQuery(estmt, into, queryString, params, dest, completionTag);
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index 8cfbcf43f799cfd9ca6be362f4288b764bc7185a..ff3108ce72bc6acf5fd930dd066401f0c1e25862 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -222,12 +222,10 @@ type_in_list_does_not_exist_skipping(List *typenames, const char **msg,
 
 	foreach(l, typenames)
 	{
-		TypeName   *typeName = (TypeName *) lfirst(l);
+		TypeName   *typeName = castNode(TypeName, lfirst(l));
 
 		if (typeName != NULL)
 		{
-			Assert(IsA(typeName, TypeName));
-
 			if (!OidIsValid(LookupTypeNameOid(NULL, typeName, true)))
 			{
 				/* type doesn't exist, try to find why */
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index f9fb27658f7fba3ed49cf46d1bca68823c2fbdd0..5d61a0195ed82dcbcaf2c0e22b76514c87c71429 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -1493,25 +1493,25 @@ ExplainNode(PlanState *planstate, List *ancestors,
 										   planstate, es);
 			break;
 		case T_Agg:
-			show_agg_keys((AggState *) planstate, ancestors, es);
+			show_agg_keys(castNode(AggState, planstate), ancestors, es);
 			show_upper_qual(plan->qual, "Filter", planstate, ancestors, es);
 			if (plan->qual)
 				show_instrumentation_count("Rows Removed by Filter", 1,
 										   planstate, es);
 			break;
 		case T_Group:
-			show_group_keys((GroupState *) planstate, ancestors, es);
+			show_group_keys(castNode(GroupState, planstate), ancestors, es);
 			show_upper_qual(plan->qual, "Filter", planstate, ancestors, es);
 			if (plan->qual)
 				show_instrumentation_count("Rows Removed by Filter", 1,
 										   planstate, es);
 			break;
 		case T_Sort:
-			show_sort_keys((SortState *) planstate, ancestors, es);
-			show_sort_info((SortState *) planstate, es);
+			show_sort_keys(castNode(SortState, planstate), ancestors, es);
+			show_sort_info(castNode(SortState, planstate), es);
 			break;
 		case T_MergeAppend:
-			show_merge_append_keys((MergeAppendState *) planstate,
+			show_merge_append_keys(castNode(MergeAppendState, planstate),
 								   ancestors, es);
 			break;
 		case T_Result:
@@ -1523,11 +1523,11 @@ ExplainNode(PlanState *planstate, List *ancestors,
 										   planstate, es);
 			break;
 		case T_ModifyTable:
-			show_modifytable_info((ModifyTableState *) planstate, ancestors,
+			show_modifytable_info(castNode(ModifyTableState, planstate), ancestors,
 								  es);
 			break;
 		case T_Hash:
-			show_hash_info((HashState *) planstate, es);
+			show_hash_info(castNode(HashState, planstate), es);
 			break;
 		default:
 			break;
@@ -2183,7 +2183,6 @@ show_tablesample(TableSampleClause *tsc, PlanState *planstate,
 static void
 show_sort_info(SortState *sortstate, ExplainState *es)
 {
-	Assert(IsA(sortstate, SortState));
 	if (es->analyze && sortstate->sort_Done &&
 		sortstate->tuplesortstate != NULL)
 	{
@@ -2217,7 +2216,6 @@ show_hash_info(HashState *hashstate, ExplainState *es)
 {
 	HashJoinTable hashtable;
 
-	Assert(IsA(hashstate, HashState));
 	hashtable = hashstate->hashtable;
 
 	if (hashtable)
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 22aecb24f927a629ba0f781a97437d04819a9768..ec833c382dcf20943cfff8fc2e0dae78976a89c5 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -578,9 +578,8 @@ update_proconfig_value(ArrayType *a, List *set_items)
 
 	foreach(l, set_items)
 	{
-		VariableSetStmt *sstmt = (VariableSetStmt *) lfirst(l);
+		VariableSetStmt *sstmt = castNode(VariableSetStmt, lfirst(l));
 
-		Assert(IsA(sstmt, VariableSetStmt));
 		if (sstmt->kind == VAR_RESET_ALL)
 			a = NULL;
 		else
@@ -971,9 +970,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
 	{
 		ListCell   *lc;
 
-		Assert(IsA(transformDefElem, List));
-
-		foreach(lc, (List *) transformDefElem)
+		foreach(lc, castNode(List, transformDefElem))
 		{
 			Oid			typeid = typenameTypeId(NULL, lfirst(lc));
 			Oid			elt = get_base_element_type(typeid);
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 6b5a9b6fe81ebce69cfeb015a92fa9a3c4f4fe38..b7daf1ca0a075043aca8f9c14c238be2b8e3f5d7 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -264,8 +264,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
 	 * The stored query was rewritten at the time of the MV definition, but
 	 * has not been scribbled on by the planner.
 	 */
-	dataQuery = (Query *) linitial(actions);
-	Assert(IsA(dataQuery, Query));
+	dataQuery = castNode(Query, linitial(actions));
 
 	/*
 	 * Check for active uses of the relation in the current transaction, such
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 7cfcc6de84a84f95de82e14707fb9ea67fd78d23..bc43483b94a77734bc8e94fd41dae7a658e39574 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -462,13 +462,12 @@ DefineOpClass(CreateOpClassStmt *stmt)
 	 */
 	foreach(l, stmt->items)
 	{
-		CreateOpClassItem *item = lfirst(l);
+		CreateOpClassItem *item = castNode(CreateOpClassItem, lfirst(l));
 		Oid			operOid;
 		Oid			funcOid;
 		Oid			sortfamilyOid;
 		OpFamilyMember *member;
 
-		Assert(IsA(item, CreateOpClassItem));
 		switch (item->itemtype)
 		{
 			case OPCLASS_ITEM_OPERATOR:
@@ -847,13 +846,12 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 	 */
 	foreach(l, items)
 	{
-		CreateOpClassItem *item = lfirst(l);
+		CreateOpClassItem *item = castNode(CreateOpClassItem, lfirst(l));
 		Oid			operOid;
 		Oid			funcOid;
 		Oid			sortfamilyOid;
 		OpFamilyMember *member;
 
-		Assert(IsA(item, CreateOpClassItem));
 		switch (item->itemtype)
 		{
 			case OPCLASS_ITEM_OPERATOR:
@@ -981,12 +979,11 @@ AlterOpFamilyDrop(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
 	 */
 	foreach(l, items)
 	{
-		CreateOpClassItem *item = lfirst(l);
+		CreateOpClassItem *item = castNode(CreateOpClassItem, lfirst(l));
 		Oid			lefttype,
 					righttype;
 		OpFamilyMember *member;
 
-		Assert(IsA(item, CreateOpClassItem));
 		switch (item->itemtype)
 		{
 			case OPCLASS_ITEM_OPERATOR:
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c4b0011bdd61e3e0589fb35a559090e4f7342987..04b5d9a943ca5e93c55120d106a86dc6aaff0adb 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5932,12 +5932,11 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
 						colName)));
 
 	/* Generate new proposed attoptions (text array) */
-	Assert(IsA(options, List));
 	datum = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
 							&isnull);
 	newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
-									 (List *) options, NULL, NULL, false,
-									 isReset);
+									 castNode(List, options), NULL, NULL,
+									 false, isReset);
 	/* Validate new options */
 	(void) attribute_reloptions(newOptions, true);
 
@@ -7141,8 +7140,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
 	bool		found = false;
 	ObjectAddress address;
 
-	Assert(IsA(cmd->def, Constraint));
-	cmdcon = (Constraint *) cmd->def;
+	cmdcon = castNode(Constraint, cmd->def);
 
 	conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
 
@@ -9348,9 +9346,7 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
 					IndexStmt  *indstmt;
 					Oid			indoid;
 
-					Assert(IsA(cmd->def, IndexStmt));
-
-					indstmt = (IndexStmt *) cmd->def;
+					indstmt = castNode(IndexStmt, cmd->def);
 					indoid = get_constraint_index(oldId);
 
 					if (!rewrite)
@@ -9373,9 +9369,7 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
 				{
 					Constraint *con;
 
-					Assert(IsA(cmd->def, Constraint));
-
-					con = (Constraint *) cmd->def;
+					con = castNode(Constraint, cmd->def);
 					con->old_pktable_oid = refRelId;
 					/* rewriting neither side of a FK */
 					if (con->contype == CONSTR_FOREIGN &&
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 68fa7acfb178c0d6b86edc04fcd0eb4521b13237..f067d0a7bb939f3412a568c8c413e434611e00fd 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -340,9 +340,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 
 		foreach(lc, varList)
 		{
-			TriggerTransition   *tt = (TriggerTransition *) lfirst(lc);
-
-			Assert(IsA(tt, TriggerTransition));
+			TriggerTransition   *tt = castNode(TriggerTransition, lfirst(lc));
 
 			if (!(tt->isTable))
 				ereport(ERROR,
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index e6fdac34aea11ae3259111c7d8122f62c05fcf9f..b746982d2ee39b5790981f72e8a5a47c0242cf66 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1396,11 +1396,9 @@ roleSpecsToIds(List *memberNames)
 
 	foreach(l, memberNames)
 	{
-		RoleSpec   *rolespec = (RoleSpec *) lfirst(l);
+		RoleSpec   *rolespec = castNode(RoleSpec, lfirst(l));
 		Oid			roleid;
 
-		Assert(IsA(rolespec, RoleSpec));
-
 		roleid = get_rolespec_oid(rolespec, false);
 		result = lappend_oid(result, roleid);
 	}
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 1f008b075666342c0cbae3486c3fbc4ea9080d3a..7d76f567a8e5dd663b2822338d85ea84559778b4 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -516,9 +516,8 @@ DefineView(ViewStmt *stmt, const char *queryString,
 
 		foreach(targetList, viewParse->targetList)
 		{
-			TargetEntry *te = (TargetEntry *) lfirst(targetList);
+			TargetEntry *te = castNode(TargetEntry, lfirst(targetList));
 
-			Assert(IsA(te, TargetEntry));
 			/* junk columns don't get aliases */
 			if (te->resjunk)
 				continue;
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c
index 1ca4bcb117c8562256df35fcea6ca2dbf063bf25..d3802079f5e70b66b57f696028deff790a5d28e8 100644
--- a/src/backend/executor/execAmi.c
+++ b/src/backend/executor/execAmi.c
@@ -403,11 +403,12 @@ ExecSupportsMarkRestore(Path *pathnode)
 			return true;
 
 		case T_CustomScan:
-			Assert(IsA(pathnode, CustomPath));
-			if (((CustomPath *) pathnode)->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
+		{
+			CustomPath *customPath = castNode(CustomPath, pathnode);
+			if (customPath->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
 				return true;
 			return false;
-
+		}
 		case T_Result:
 
 			/*
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 19dd0b264bced6a75f07d69f49f8c19704d37694..4566219ca8b0b854038444dfd7427430d1abc896 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -4640,10 +4640,9 @@ ExecInitExpr(Expr *node, PlanState *parent)
 				cstate->arg = ExecInitExpr(caseexpr->arg, parent);
 				foreach(l, caseexpr->args)
 				{
-					CaseWhen   *when = (CaseWhen *) lfirst(l);
+					CaseWhen   *when = castNode(CaseWhen, lfirst(l));
 					CaseWhenState *wstate = makeNode(CaseWhenState);
 
-					Assert(IsA(when, CaseWhen));
 					wstate->xprstate.evalfunc = NULL;	/* not used */
 					wstate->xprstate.expr = (Expr *) when;
 					wstate->expr = ExecInitExpr(when->expr, parent);
@@ -5137,9 +5136,8 @@ ExecCleanTargetListLength(List *targetlist)
 
 	foreach(tl, targetlist)
 	{
-		TargetEntry *curTle = (TargetEntry *) lfirst(tl);
+		TargetEntry *curTle = castNode(TargetEntry, lfirst(tl));
 
-		Assert(IsA(curTle, TargetEntry));
 		if (!curTle->resjunk)
 			len++;
 	}
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index cbb2bcb5684d91cef7ea127957f467cf009da3ba..f002ee2561fc1ca4cd0bf33365496c0b74a002d6 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -160,10 +160,7 @@ ExecResetTupleTable(List *tupleTable,	/* tuple table */
 
 	foreach(lc, tupleTable)
 	{
-		TupleTableSlot *slot = (TupleTableSlot *) lfirst(lc);
-
-		/* Sanity checks */
-		Assert(IsA(slot, TupleTableSlot));
+		TupleTableSlot *slot = castNode(TupleTableSlot, lfirst(lc));
 
 		/* Always release resources and reset the slot to empty */
 		ExecClearTuple(slot);
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index e4a1da4dbbf4b2be0475fedfcfe64be498f13094..15c709139add17d1a733b38ca345effcfbc82ac0 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -479,19 +479,17 @@ init_execution_state(List *queryTree_list,
 
 	foreach(lc1, queryTree_list)
 	{
-		List	   *qtlist = (List *) lfirst(lc1);
+		List	   *qtlist = castNode(List, lfirst(lc1));
 		execution_state *firstes = NULL;
 		execution_state *preves = NULL;
 		ListCell   *lc2;
 
 		foreach(lc2, qtlist)
 		{
-			Query	   *queryTree = (Query *) lfirst(lc2);
+			Query	   *queryTree = castNode(Query, lfirst(lc2));
 			PlannedStmt *stmt;
 			execution_state *newes;
 
-			Assert(IsA(queryTree, Query));
-
 			/* Plan the query if needed */
 			if (queryTree->commandType == CMD_UTILITY)
 			{
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index e4992134bd0a1dfec4032a1c3e69a8b6f315b4e6..5c6079af808487cf41637f617662c5cd9ccad118 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -2572,9 +2572,8 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 
 		if (phase > 0)
 		{
-			aggnode = list_nth(node->chain, phase - 1);
-			sortnode = (Sort *) aggnode->plan.lefttree;
-			Assert(IsA(sortnode, Sort));
+			aggnode = castNode(Agg, list_nth(node->chain, phase - 1));
+			sortnode = castNode(Sort, aggnode->plan.lefttree);
 		}
 		else
 		{
@@ -3010,10 +3009,9 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 		 */
 		foreach(arg, pertrans->aggref->args)
 		{
-			TargetEntry *source_tle = (TargetEntry *) lfirst(arg);
+			TargetEntry *source_tle = castNode(TargetEntry, lfirst(arg));
 			TargetEntry *tle;
 
-			Assert(IsA(source_tle, TargetEntry));
 			tle = flatCopyTargetEntry(source_tle);
 			tle->resno += column_offset;
 
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index 610797b36b63a1144e0814f92d6d19e9fec9f960..8f4e0f527e4f847c6d15c20b7898e5d0c4b1d286 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -210,7 +210,7 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
 	prmdata = &(estate->es_param_exec_vals[node->cteParam]);
 	Assert(prmdata->execPlan == NULL);
 	Assert(!prmdata->isnull);
-	scanstate->leader = (CteScanState *) DatumGetPointer(prmdata->value);
+	scanstate->leader = castNode(CteScanState, DatumGetPointer(prmdata->value));
 	if (scanstate->leader == NULL)
 	{
 		/* I am the leader */
@@ -223,7 +223,6 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
 	else
 	{
 		/* Not the leader */
-		Assert(IsA(scanstate->leader, CteScanState));
 		/* Create my own read pointer, and ensure it is at start */
 		scanstate->readptr =
 			tuplestore_alloc_read_pointer(scanstate->leader->cte_table,
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index a27430242a5621763ce1a75c41fddb57aab41a57..16343a56df73fa5d83c2359786e03e083007cd8e 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -35,8 +35,8 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
 	 * methods field correctly at this time.  Other standard fields should be
 	 * set to zero.
 	 */
-	css = (CustomScanState *) cscan->methods->CreateCustomScanState(cscan);
-	Assert(IsA(css, CustomScanState));
+	css = castNode(CustomScanState,
+				   cscan->methods->CreateCustomScanState(cscan));
 
 	/* ensure flags is filled correctly */
 	css->flags = cscan->flags;
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 6e576ad0b38c2b21fa82e6521d072475d2b04c7f..8a04294b40207e4ff2c33ad0499a21bd45994f67 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -519,12 +519,9 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
 	hoperators = NIL;
 	foreach(l, hjstate->hashclauses)
 	{
-		FuncExprState *fstate = (FuncExprState *) lfirst(l);
-		OpExpr	   *hclause;
+		FuncExprState *fstate = castNode(FuncExprState, lfirst(l));
+		OpExpr	   *hclause = castNode(OpExpr, fstate->xprstate.expr);
 
-		Assert(IsA(fstate, FuncExprState));
-		hclause = (OpExpr *) fstate->xprstate.expr;
-		Assert(IsA(hclause, OpExpr));
 		lclauses = lappend(lclauses, linitial(fstate->args));
 		rclauses = lappend(rclauses, lsecond(fstate->args));
 		hoperators = lappend_oid(hoperators, hclause->opno);
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index f1bf6fdf9f02fce05db855e0d53b442e63332cf6..b098034337787419c049702069ed70ff6302e28f 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -401,12 +401,10 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
 	epq_arowmarks = NIL;
 	foreach(lc, node->rowMarks)
 	{
-		PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
+		PlanRowMark *rc = castNode(PlanRowMark, lfirst(lc));
 		ExecRowMark *erm;
 		ExecAuxRowMark *aerm;
 
-		Assert(IsA(rc, PlanRowMark));
-
 		/* ignore "parent" rowmarks; they are irrelevant at runtime */
 		if (rc->isParent)
 			continue;
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index e35603964b7f494c80a7403aec64e7e115ebf6ab..95e158970c30958596f23a842b5d156e965a280d 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1958,11 +1958,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 	 */
 	foreach(l, node->rowMarks)
 	{
-		PlanRowMark *rc = (PlanRowMark *) lfirst(l);
+		PlanRowMark *rc = castNode(PlanRowMark, lfirst(l));
 		ExecRowMark *erm;
 
-		Assert(IsA(rc, PlanRowMark));
-
 		/* ignore "parent" rowmarks; they are irrelevant at runtime */
 		if (rc->isParent)
 			continue;
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index f8a2cd446a2590ab1d53d6decf0b70e5d2be2409..8f419a13acd41a147d27c4b2822858392e55d3bf 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -808,8 +808,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 		else if (and_clause((Node *) sstate->testexpr->expr))
 		{
 			/* multiple combining operators */
-			Assert(IsA(sstate->testexpr, BoolExprState));
-			oplist = ((BoolExprState *) sstate->testexpr)->args;
+			oplist = castNode(BoolExprState, sstate->testexpr)->args;
 		}
 		else
 		{
@@ -829,8 +828,8 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 		i = 1;
 		foreach(l, oplist)
 		{
-			FuncExprState *fstate = (FuncExprState *) lfirst(l);
-			OpExpr	   *opexpr = (OpExpr *) fstate->xprstate.expr;
+			FuncExprState *fstate = castNode(FuncExprState, lfirst(l));
+			OpExpr	   *opexpr = castNode(OpExpr, fstate->xprstate.expr);
 			ExprState  *exstate;
 			Expr	   *expr;
 			TargetEntry *tle;
@@ -839,8 +838,6 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 			Oid			left_hashfn;
 			Oid			right_hashfn;
 
-			Assert(IsA(fstate, FuncExprState));
-			Assert(IsA(opexpr, OpExpr));
 			Assert(list_length(fstate->args) == 2);
 
 			/* Process lefthand argument */
@@ -1218,10 +1215,8 @@ ExecAlternativeSubPlan(AlternativeSubPlanState *node,
 					   bool *isNull)
 {
 	/* Just pass control to the active subplan */
-	SubPlanState *activesp = (SubPlanState *) list_nth(node->subplans,
-													   node->active);
-
-	Assert(IsA(activesp, SubPlanState));
+	SubPlanState *activesp = castNode(SubPlanState,
+									  list_nth(node->subplans, node->active));
 
 	return ExecSubPlan(activesp, econtext, isNull);
 }
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c
index bdba9e0bfcde501a2cd113f43c57c600decf72e8..23b5b9498576512067bddfbfdcae0f64208f7a2b 100644
--- a/src/backend/executor/nodeWorktablescan.c
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -95,8 +95,8 @@ ExecWorkTableScan(WorkTableScanState *node)
 		param = &(estate->es_param_exec_vals[plan->wtParam]);
 		Assert(param->execPlan == NULL);
 		Assert(!param->isnull);
-		node->rustate = (RecursiveUnionState *) DatumGetPointer(param->value);
-		Assert(node->rustate && IsA(node->rustate, RecursiveUnionState));
+		node->rustate = castNode(RecursiveUnionState, DatumGetPointer(param->value));
+		Assert(node->rustate);
 
 		/*
 		 * The scan tuple type (ie, the rowtype we expect to find in the work